0

I want to use this Recursive Function to convert a php array into an array of parent and childs.

I have a this Cell:

class MenuCell extends Cell {
  public function display($menu) {
    $this->loadModel('Menus');
    $menus = $this -> Menus -> find('all', [
      'contain' => ['MenuItems']
    ]) -> where(['id' => $menu]);

    $menus = $this -> buildTree($menus);


    $this -> set(compact('menus'));
    $this -> set('_serialize', ['menus']);

  }

  public function buildTree($ar, $pid = null) {
    $op = array();
    foreach($ar as $item) {
      if ($item['parentId'] == $pid) {
        $op[$item['id']] = array(
          'name' => $item['name'],
          'parentId' => $item['parentId']
        );
        // using recursion
        $children = $this ->buildTree($ar, $item['id']);
        if ($children) {
          $op[$item['id']]['children'] = $children;
        }
      }
    }
    return $op;
  }


}

But it gives me this error: enter image description here

However if i do the samething in controller, It works very fine. Any help would save my day.

4
  • 2
    Before asking such questions you should debug such problems first! On a related note, why don't you use find('threaded')? Commented May 25, 2016 at 13:39
  • I don't need to find threaded from the model. I've found everything in the array and then want to perform an operation on that array. Sorry i didnt see those errors. I'll take care next time Commented May 25, 2016 at 13:41
  • @ManjeetBarnala that's the best a terrible poor hack and clearly not a solution. 1000 - That's 16 minutes. I'm sure the user has left long before or your shitty code will blow up the memory limit before or another error happens. Fix the problem, not the symptoms! Commented May 25, 2016 at 16:08
  • What do you suggest sir? Commented May 25, 2016 at 16:51

1 Answer 1

1

If you want create dinamic menu try this:

First check your MenusTable, your table should have field with parent id (parent_id in my example) and create relationship belongsTo, hasMany

Menus Model

class MenusTable extends Table
{

    public function initialize(array $config)
    {
        parent::initialize($config);

        $this->table('menus');
        $this->displayField('name');
        $this->primaryKey('id');

        $this->addBehavior('Timestamp');
        $this->addBehavior('Tree');

        $this->belongsTo('ParentMenus', [
            'className' => 'Menus',
            'foreignKey' => 'parent_id'
        ]);
        $this->hasMany('ChildMenus', [
            'className' => 'Menus',
            'foreignKey' => 'parent_id'
        ]);
    }

}

MenuCell

class MenuCell extends Cell {
    public function display($menu) {
        $this->loadModel('Menus');

        $menus = $this->Menus->find('threaded')->where(['id'=>$menu])->toArray();

        $menus = $this->buildTree($menus);

        $this->set(compact('menus'));
        $this->set('_serialize', ['menus']);
    }

    //Recursive function:

    protected function buildTree($menus) {

        foreach($menus as $element) {

            if(!is_array($element)) {
                $element = $element->toArray();
            }

            //Elements each menu array  
            $menu['name'] = $element['name'];
            $menu['url'] = $element['url'];

            foreach($element as $key => $value){

                if(is_array($value)) {
                    $menu[$key] = $this->buildTree($value);
                }

            }
            $resultMenu[] = $menu;
        }

        if(isset($resultMenu)) {
            return $resultMenu;
        }
    }
}

Example Result:

[
    (int) 0 => [
        'name' => 'Level_1',
        'url' => '/',
        'children' => null
    ],
    (int) 1 => [
        'name' => 'Level_1',
        'url' => '/',
        'children' => [
            (int) 0 => [
                'name' => 'Level_1.1',
                'url' => '/',
                'children' => [
                    (int) 0 => [
                        'name' => 'Level_1.1.1',
                        'url' => '/',
                        'children' => null
                    ],
                    (int) 1 => [
                        'name' => 'Level_1.1.1',
                        'url' => '/',
                        'children' => null
                    ]
                ]
            ],
            (int) 1 => [
                'name' => 'Level_1.1',
                'url' => '/',
                'children' => null
            ]
        ]
    ],
    (int) 2 => [
        'name' => 'Level_1',
        'url' => '/',
        'children' => null
    ],
    (int) 3 => [
        'name' => 'Level_1',
        'url' => '/',
        'children' => null
    ]
]   
Sign up to request clarification or add additional context in comments.

1 Comment

Yes I did the same thing earlier. I used the tree behavior and it handled everything itself. Thanks.

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.