0

I need help with my array. For several hours trying to find a solution but I can not cope. I tried to do it in such a way, however, the code turned out to be completely useless.

private function findKey($array, $keySearch,$app,$klucz='')
{
    foreach ($array as $key => $item) {
        if ($key == $keySearch) {
            $c2 = [];
            $cache = [
                'nazwa'=>$app->nazwa,
                'link'=>$app->link,
                'child'=>[]
            ];

            // echo $klucz; echo '<br />';

            if($klucz && $klucz != '/'){
                // echo $klucz;
                // $k = explode('/',$klucz);
                // $url   = "/2/22/";
                // debug($klucz);
                $parts = explode('/',$klucz);
                debug($klucz);
                debug($parts);

                $x = 0;
                $last = $parts[count($parts)-1];
                $arr = array();
                while ($bottom = array_pop($parts)) {  
                    if($bottom != $last){

                        $arr = array($bottom => $arr);
                        $x++;
                    }else{
                        array_push($arr, $cache);
                    }


                }

                // $arr['child'] = $cache;
                debug($arr);
                // exit;

                // print_r($output);
                // exit;

                // self::buildKey($k);

                // print_r($c2);

                echo "<br />";
            }


        }
        else {
            $klucz = $klucz.'/'.$key;
            if (is_array($item) && self::findKey($item, $keySearch,$app,$klucz)) {
               // return true;
            }
        }
    }

    // return false;
}

I need to create array from loop. From mysql I get data as object, and this data view like this:

|id|nazwa|link|parent|

|1|abc|abcc|0|

|2|aaa|bbb|1|

|3|aas|bbc|2|

|4|asdasd|adsasd|2|

|5|asdasd|serae|4|

|6|rywer|twet|0|

And now I need array whose use data from mysql and display it at array like this:

array(
    [1]=>array(
        id=>1,
        nazwa=>abc
        link=>abcc
        child=>array(

            [2]=>array(
                id=>2,
                nazwa=>aaa
                link=>bbb
                child=>array(

                    [3]=>array(
                        id=>3,
                        nazwa=>aas
                        link=>bbc
                        child=>array(

                        )
                    ),

                    [4]=>array(
                        id=>4,
                        nazwa=>asdasd
                        link=>adsasd
                        child=>array(

                            [5]=>array(
                                id=>5,
                                nazwa=>asdasd
                                link=>serae
                                child=>array(

                                )
                            ),
                        )
                    ),
                )
            )
        )
    ),

    [6]=>array(
        id=>6,
        nazwa=>rywer
        link=>twet
        child=>array(

        )
    ),
)

I think just a simple, good loop or function but I can not deal with it.

2 Answers 2

1

Try my code link to online demo:

<?php
$data = array(
    array(
        'id' => 1,
        'name' => 'abc',
        'link' => 'abcc',
        'parent' => 0
    ),
    array(
        'id' => 2,
        'name' => 'aaa',
        'link' => 'bbb',
        'parent' => 1
    ),
    array(
        'id' => 3,
        'name' => 'aas',
        'link' => 'bbc',
        'parent' => 2
    ),
    array(
        'id' => 4,
        'name' => 'asdasd',
        'link' => 'adsasd',
        'parent' => 2
    ),
    array(
        'id' => 5,
        'name' => 'asdasd',
        'link' => 'serae',
        'parent' => 4
    ),
    array(
        'id' => 6,
        'name' => 'rywer',
        'link' => 'twet',
        'parent' => 0
    )
);

function buildMenu($data) {
    usort($data, function($a, $b) {
        if ($a['parent'] == $b['parent']) {
            if ($a['id'] == $b['id']) {
                return 0;
            }
            return ($a['id'] < $b['id']) ? -1 : 1;
        }
        return ($a['parent'] < $b['parent']) ? -1 : 1;
    });

    $shortcuts = array();
    $menu = array();

    foreach($data as &$row) {
        if ($row['parent'] <= 0) {
            $menu[] = &$row;
            $shortcuts[$row['id']] = &$row;
            continue;
        } else {
            $parent = $row['parent'];
            if (!isset($shortcuts[$parent])) {
                throw new \Exception("Menu cannot be build");
            }
            $parentItem = &$shortcuts[$parent];
        }
        if (!isset($parentItem['child'])) {
            $parentItem['child'] = array();
        }
        $parentItem['child'][] = &$row;
        $shortcuts[$row['id']] = &$row;
    }
    return $menu;
}

print_r(buildMenu($data));

It uses references to keep it clean. On the beggining of buildMenu function I have also sorted your sorce array to have data sorted by parent ID, increasingly.

Please also consider using english variable names.

If you would like to generate <ul> menu from this array, use this code:

$menu = '<ul>';
function buildUl($data) {
    $menuHtml = '';
    foreach ($data as $menuItem) {
        $menuHtml .= '<li>';
        $menuHtml .= '<a href="'.$menuItem['link'].'">'.$menuItem['name'].'</a>';
        if (!empty($menuItem['child'])) {
            $menuHtml .= '<ul>';
            $menuHtml .= buildUl($menuItem['child']);
            $menuHtml .= '</ul>';
        }
        $menuHtml .= '</li>';
    }

    return $menuHtml;
}
$menu .= buildUl(buildMenu($data));
$menu .= '</ul>';

echo $menu;

Updated example: http://sandbox.onlinephpfunctions.com/code/27cfa95c066be9b1526b71566e2ec2f2093bdc34

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks it works, but do you know how from this array generate <ul><li><ul>...</ul></li></ul> html code ? :)
Yes, I have updated my answer with an example. Anyway, your menu structure is the most ugliest way to build nested menu. Please consider usage of preorder tree (commonly known as left-right tree).
1

Things are way easier when you use objects:

$data = [
    ['id' => 1, 'nazwa' => 'abc',    'link' => 'abcc',   'parent' => 0],
    ['id' => 2, 'nazwa' => 'aaa',    'link' => 'bbb',    'parent' => 1],
    ['id' => 3, 'nazwa' => 'aas',    'link' => 'bbc',    'parent' => 2],
    ['id' => 4, 'nazwa' => 'asdasd', 'link' => 'adsasd', 'parent' => 2],
    ['id' => 5, 'nazwa' => 'asdasd', 'link' => 'serae',  'parent' => 4],
    ['id' => 6, 'nazwa' => 'rywer',  'link' => 'twet',   'parent' => 0],

];

$objectTree = [];
$objects = [];

foreach ($data as $row) {
    $obj = (object)$row;
    $obj->childs = [];
    $objects[$obj->id] = $obj;
}

foreach ($objects as $obj) {
    if ($obj->parent == 0) {
        $objectTree[] = $obj;
    } else {
        $objects[$obj->parent]->childs[] = $obj;
    }
}

var_export($objectTree);

Demo: http://rextester.com/RZRQLX19028

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.