0

Let's say I append a value to an array, which has been appended to an array:

$a = array();
$b = array();
$b[] = 42;
$a[] = $b;

echo $a[0][0];    

>> 42

The output is (as expected) "42". Now let's say I make a small change in the order of my code. This change should make no difference at all, as arrays should be passed by reference.

$a = array();
$b = array();
$a[] = $b;
$b[] = 42;

echo $a[0][0];

>> Notice: Undefined offset: 0 in /opt/iceberg/web/upload/auth.php on line 111

What gives? While reducing my code down to this simplified example, I couldn't shake the feeling that I had made some mistake that should be obvious. Any help would be appreciated!

Solution

You can force a by reference assignment:

$a = array();
$b = array();
$a[] =& $b;
$b[] = 42;

echo $a[0][0];

>> 42

Addendum: Upon usage in more complicated cases, =& works in mysterious ways and causes some very strange (to me) behaviour. I think for PHP novices, it's best to stick with the by value assignment.

Monkey Boson
  • 1,250
  • 4
  • 11
  • 21
  • `print_r()` is great for looking at these in more detail: http://www.php.net/manual/en/function.print-r.php – msturdy Sep 05 '13 at 19:57
  • Possible duplicate of http://stackoverflow.com/questions/8897749/php-array-assign-by-copying-value-or-by-reference –  Sep 05 '13 at 19:57
  • Arrays are passed by value. – Niet the Dark Absol Sep 05 '13 at 19:57
  • 1
    You could pass it by reference by using `$a =& $b` – Rob Sep 05 '13 at 20:01
  • "This change should make no difference at all, as arrays should be passed by reference." Why *should* they be? You are starting with a false premise. And it's obvious that they are not, e.g. `$a = []; function f($a) { $a[] = 42; } f($a);` and afterwards `$a` is still empty. – Jon Sep 05 '13 at 20:03
  • @Jon Perhaps a better phrasing would be "I expect that arrays would be passed by reference, as that's how it works in all the other languages I'm familiar with." Also, the fact that there's no function involved definitely confounded it for me. I've seen by value function arguments, but I've never seen by value assignment. – Monkey Boson Sep 05 '13 at 20:12
  • @MonkeyBoson: If you feel strongly about the language surprising you in that way, stay *well* away from PHP. ;-) – Jon Sep 05 '13 at 20:19

1 Answers1

2

By Value, everything in PHP is byval except objects (and possibly resources? it's been a while). $a[0] holds a zero length array.

If we go back in time a little (to PHP 4), everything was pass-by-value. Technically $a = new thing(); would create a new instance of thing, duplicate it into $a, then destroy the original. Which was clearly crazy talk. This was horrible for performance when dealing with objects, but made things quite consistent. The "arrays plus some hacked on fairy dust" object model clearly needed some upgrading, which is what PHP 5 introduced. For large swaths of PHP's user base (think: guy in the office who knew how to reset the printer, now in charge of maintaining the website) the by-value nature of things makes things simple, and hard to categorically screw up.

More Detail: Technically, it's not by-value, it's all copy on write.

preinheimer
  • 3,712
  • 20
  • 34
  • This really breaks the rule of least surprise for me, as every other language I'm familiar with passes arrays around by reference. However, as Rob pointed out, you can force a by reference assignment. The fix for the second code block would be to change the third line to `$a[] =& $b;` – Monkey Boson Sep 05 '13 at 20:06