aspirinemaga
aspirinemaga

Reputation: 3937

How to construct an array recursively based on each parent id

I have a nested list of categories which DB looks something like this:

id      parent_id       title
83      81              test3
86      83              test1
87      83              test2
94      87              subtest2.1
95      87              subtest2.2
...etc...

I need to add all child element ids into the $checked_elements array of each parent id.

So if some specific id is selected, it's automatically added into the array of $checked_elements. Here how it looks like:

enter image description here

I'am stuck with the recursive function, on how to add recursively child items of each parent item id ? My function won't go deeper then the 2nd level, can anyone tell me how to work it out so it will check for all child items ?

private function delete( ){

    // Collect all checked elements into the array
    $checked_elements = $this->input->post('checked');

    // Recursive function to check for child elementts
    foreach( $checked_elements as $key => $value ){

        // Get records where parent_id is equal to $value (checked item's id)
        $childs = $this->categories_model->get_by(array('parent_id' => $value));

        // Add found record's id into the array 
        foreach( $childs as $child ){

            $checked_elements[] => $child->id;

        }

    }

}

Upvotes: 0

Views: 992

Answers (1)

gog
gog

Reputation: 11347

You can try passing the accumulator array around by reference:

function collect($ids, &$items) {
    foreach($ids as $id){
        $items[] = $id;
        $childs = $this->categories_model->get_by(array('parent_id' => $id));
        collect(array_column($childs, 'id'), $items);
    }
    return $items;
}

function delete( ){
    $items = array();
    collect($this->input->post('checked'), $items);
    //... delete $items
}

In php 5.5+ you can also use generators in a way similar to this:

function collect($ids) {
    foreach($ids as $id) {
        yield $id;
        $childs = $this->categories_model->get_by(array('parent_id' => $id));
        foreach(collect(array_column($childs, 'id')) as $id)
            yield $id;
}


function delete( ){
    $ids = collect($this->input->post('checked'));

I assume your tree is rather small, otherwise I'd suggest a more efficient approach, like nested sets.

If your php version doesn't support array_column, you can use this shim.

Upvotes: 1

Related Questions