2

I have a global array in which I am trying to update a value (remain persistent) and then display it.
I get no error but the array never gets updated.

<?php
$anchor = 'bird';
$stuff = array('apple', 'bird', 'frog');

function insert($anchor, $stuff){
    foreach($stuff as $part){
        $new_array = array($anchor => rand());
        if($part == $anchor){
            array_push($stuff, $new_array);
        }
    }
}

for($x = 0; $x < 2; $x++){
    insert($anchor, $stuff);
    var_dump($stuff);
}

output:

array(3) {
  [0]=>
  string(5) "apple"
  [1]=>
  string(4) "bird"
  [2]=>
  string(4) "frog"
}
array(3) {
  [0]=>
  string(5) "apple"
  [1]=>
  string(4) "bird"
  [2]=>
  string(4) "frog"
}

expected output:

{'bird' => 674568765}
{'bird' => 986266261}

How do I update an array within a function, so that the changes are reflected globally (persistent)?

showdev
  • 28,454
  • 37
  • 55
  • 73
dooode
  • 197
  • 1
  • 8
  • 1
    PHP variables are passed into functions *by value* not by reference. http://stackoverflow.com/questions/879/are-php-variables-passed-by-value-or-by-reference#885 – Jonathan M Aug 17 '16 at 17:58
  • 1
    To update the original array, you'll need to return a value from the function and assign it to the array variable. – Jonathan M Aug 17 '16 at 17:59

3 Answers3

2

Pass the variable $stuff by reference. Note the & in the function parameters.

function insert($anchor, &$stuff){    // note the & mark
        foreach($stuff as $part){
                $new_array = array($anchor => rand());
                if($part == $anchor){
                        array_push($stuff, $new_array);
                }
        }
}
Imesha Sudasingha
  • 3,462
  • 1
  • 23
  • 34
2

As others have mentioned: by default, PHP function arguments are passed by value, meaning that a value changed inside a function does not change outside of the function.

I suggest returning the new $stuff value from your function:

<?php

$anchor = 'bird';
$stuff = array('apple', 'bird', 'frog');

function insert($anchor, $stuff){
  foreach($stuff as $part){
    $new_array = array($anchor => rand());
    if($part == $anchor){
      array_push($stuff, $new_array);
    }
  }
  return $stuff;
}

for($x = 0; $x < 2; $x++){
  $stuff=insert($anchor, $stuff);
}

echo"<pre>".print_r($stuff,true)."</pre>";

?>
Array
(
    [0] => apple
    [1] => bird
    [2] => frog
    [3] => Array
        (
            [bird] => 618490127
        )

    [4] => Array
        (
            [bird] => 1869073273
        )

)

Other solutions propose passing by reference, to which I'm not opposed. But I have definitely run into buggy code in which it wasn't immediately clear that a function was changing a value, and I've been confused by unexpected loop behavior. As a result, I generally prefer arguably more readable/maintainable code that returns a new value.

See When to pass-by-reference in PHP.
Get technical with Sara Golemon.

Community
  • 1
  • 1
showdev
  • 28,454
  • 37
  • 55
  • 73
  • 1
    This is, I believe, safer than declaring the function with reference parameters. – Jonathan M Aug 17 '16 at 18:04
  • @JonathanM They would actually be pretty much the same. Neither one is "safer" that the other. There are no exploits or issues with using a reference that wouldn't exist making a copy. By reference would actually just not make a copy of the array which would be better if you are dealing with a very large amount of data. – Jonathan Kuhn Aug 17 '16 at 18:11
  • In terms of API, I think it's better for functions to return changed values than to change them by reference. That way the programmer doesn't unknowingly get a changed value. Less likely to have a mistake. – Jonathan M Aug 17 '16 at 20:35
1

If you want changes to a variable that you pass to a function to persist after the function ends, pass the variable by reference:

Change:

function insert($anchor, $stuff)

To

function insert($anchor, &$stuff)
BeetleJuice
  • 39,516
  • 19
  • 105
  • 165