1

I currently have a code snippet where for each category, it would find the sub-categories:

   $categories = array_map(
        function($child)
        {
            $child['children'] =
                $this->getChildren(
                    $child['id'],
                    !empty($this->request->get['language_id']) ?
                        $this->request->get['language_id'] : 1
                );
            return $child;
        }, $categories);

getChildren() would recursively get the children of one category:

private function getChildren($parent_id, $language_id) {
    $this->load->model('official/category');

    $children = 
        $this->model_official_category->getCategoriesByParentId(
            $parent_id,
            $language_id
        );

    // For each child, find the children.
    foreach ($children as $child) {
        $child['children'] = $this->getChildren(
            $child['id'],
            $language_id
        );
    }

    return $children;
}

Currently, using my lambda function within the array_map(), only the sub-category's children would be retrieve, so if each sub-category has its own sub-sub-category, it would not be saved into its children.

How could I show the sub-sub-category given the sub-category we have?

What I wanted to do with my code was to take a parent, get its children, and then treat each of those children as a parent and get its children recursively, however my JSON output does not reflect that. Only the parent has children - the children has no children (despite my database having them).

theGreenCabbage
  • 5,197
  • 19
  • 79
  • 169

1 Answers1

1

The problem is that your recursion foreach loop assigns the children that it retrieves to a copy of the child data, rather than the child data itself.

To resolve this you could use foreach loop that references the child data, like so:

foreach ($children as &$child) {

However, due to a number of reasons related to how foreach is implemented internally in PHP (more info if you're interested), it would be considerably more memory efficient to use a for loop instead, as this will avoid quite a few copy-on-write copies of the child data:

for ($i = 0; isset($children[$i]); $i++) {
    $children[$i]['children'] = $this->getChildren(
        $children[$i]['id'],
        $language_id
    );
}

This is one place where using objects instead of arrays to represent the child data might be a good idea, because objects are always passed by reference (kind of) and the behaviour would be more like what you were expecting initially.

Community
  • 1
  • 1
DaveRandom
  • 87,921
  • 11
  • 154
  • 174
  • Perfect answer. Thank you. Do you suggest using for-loops instead of foreach in all situations? Coming from Java, for-loops seem automatically more intuitive and readable for me. – theGreenCabbage Nov 03 '14 at 09:40
  • @theGreenCabbage in all situations where you are looping over an array (not an object) and where you are modifying the array in the loop, yes. – DaveRandom Nov 03 '14 at 09:42