Chris
Chris

Reputation: 417

PHP code works until I make it a function

I have this code here which gives me the result I'm looking for, a nicely formatted tree of values.

    $todos = $this->db->get('todos'); //store the resulting records
    $tree = array();                  //empty array for storage
    $result = $todos->result_array(); //store results as arrays

    foreach ($result as $item){
        $id = $item['recordId'];
        $parent = $item['actionParent'];
        $tree[$id] = isset($tree[$id]) ? $item + $tree[$id] : $item;
        $tree[$parent]['_children'][] = &$tree[];
    }

    echo '<pre>';
    print_r($tree);
    echo '</pre>';

When I put the code from the foreach into a function like so, I get an empty array. What am I missing?

    function adj_tree($tree, $item){
        $id = $item['recordId'];
        $parent = $item['actionParent'];
        $tree[$id] = isset($tree[$id]) ? $item + $tree[$id] : $item;
        $tree[$parent]['_children'][] = &$tree[];
    }

    $todos = $this->db->get('todos'); //store the resulting records
    $tree = array();                  //empty array for storage
    $result = $todos->result_array(); //store results as arrays

    foreach ($result as $item){
        adj_tree($tree, $item);
    }

    echo '<pre>';
    print_r($tree);
    echo '</pre>';

Upvotes: 3

Views: 145

Answers (3)

Ozair Kafray
Ozair Kafray

Reputation: 13539

The easiest way is to pass the $tree to the function by reference. Consider changing the following line in your code

function adj_tree($tree, $item)

to

function adj_tree(&$tree, $item)

This is because in your code $tree is being passed inside the function adj_tree as a copy of the original $tree. When you pass by reference the original one is passed and the changes in it by the function adj_tree are reflected after the call.

A second (not preferred) alternative is for your function to return the modified tree so your function will look as follows:

function adj_tree($tree, $item) {
        $id = $item['recordId'];
        $parent = $item['actionParent'];
        $tree[$id] = isset($tree[$id]) ? $item + $tree[$id] : $item;
        $tree[$parent]['_children'][] = &$tree[];
        return $tree; // this is the line I have added
}

And your foreach loop will be like this:

foreach ($result as $item){
    $tree = adj_tree($tree, $item);
}

Upvotes: 5

ben
ben

Reputation: 1936

Right now the function is making a local copy of {$tree}, editing it and then discarding that copy when the function closes.

You have two options:

1) return the local copy of {$tree} and assign it to the global copy.

function adj_tree($tree, $item){
    $id = $item['recordId'];
    $parent = $item['actionParent'];
    $tree[$id] = isset($tree[$id]) ? $item + $tree[$id] : $item;
    $tree[$parent]['_children'][] = &$tree[];
    return $tree;
}
//...
foreach ($result as $item){
    $tree = adj_tree($tree, $item);
}

2) pass the array by reference and edit the global version within the function.

function adj_tree(&$tree, $item){
    $id = $item['recordId'];
    $parent = $item['actionParent'];
    $tree[$id] = isset($tree[$id]) ? $item + $tree[$id] : $item;
    $tree[$parent]['_children'][] = &$tree[];
}

Upvotes: 3

powtac
powtac

Reputation: 41050

try this:

function adj_tree($tree, $item){
    global $tree;
    // ...

or

function adj_tree(&$tree, $item){

Upvotes: 0

Related Questions