bradley546994
bradley546994

Reputation: 630

php menu generator with multidimensial array

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.

Upvotes: 0

Views: 162

Answers (2)

michail_w
michail_w

Reputation: 4481

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

Upvotes: 1

Paul Spiegel
Paul Spiegel

Reputation: 31832

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

Upvotes: 1

Related Questions