Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP: Inserting a reference into an array?

Tags:

php

reference

I'm trying to insert into an array at a certain point:

$hi = "test";
$var2 = "next";
$arr = array(&$hi);
$arr[] = &$var2; // this works
array_splice($arr, 1, 0, &$var2); // this doesn't

Why does trying to insert it into the array with splice fail and using the first method doesn't?

like image 779
Andy Lobel Avatar asked Jul 02 '12 03:07

Andy Lobel


1 Answers

The quick-and-dirty answer, but please be aware that calling this function with a reference is deprecated and may (depending on your php configuration) generate a warning:

array_splice($arr, 1, 0, array(&$var2));

The hows-and-whys answer: What's happening is pretty subtle. When you do the splice, because you have inserted a reference into that position, $var2 is actually being reassigned. You can verify it with the following code:

<?php
  $hi = "test";
  $var2 = "next";
  $arr = array(&$hi);
  $arr[] = &$var2; // this works
  printf("=== var2 before splice:\n%s\n", var_export($var2, TRUE));
  array_splice($arr, 1, 0, &$var2); // this doesn't
  printf("=== var2 after splice:\n%s\n", var_export($var2, TRUE));
?>

You will get the following result:

=== var2 before splice:
'next'
=== var2 after splice:
array (
  0 => 'next',
)

Notice that before the splice, $var2 was a string, just as you expected it to be ('next'). After the splice, though, $var2 has been replaced with an array containing one element, the string 'next'.

I think what's causing it is what the documentation says: "If replacement is not an array, it will be typecast to one (i.e. (array) $parameter)." So what is happening is this:

  • You're passing &$var2 into array as replacement.
  • Internally, php is converting &$var2 into array(&$var2). It might actually be doing something that's equivalent to $param = array($param), which means that &$var2 would be set to array(&$var2), and since it's a reference and not a copy of $var2 like it normally would be, this is affecting the variable that would normally be out of scope of the call.
  • Now it moves this new value of $var2 to the end position and inserts a copy of $var2 in the second position.

I'm not sure exactly all of the wizardry of what's happening internally, but $var is definitely being reassigned during the splice. Notice that if you use a third variable, since it's not assigning something to something that already exists as a reference, it works as expected:

<?php
  $hi = "test";
  $var2 = "next";
  $var3 = "last";
  $arr = array(&$hi);
  $arr[] = &$var2; // this works
  array_splice($arr, 1, 0, &$var3);
  printf("=== arr is now\n%s\n", var_export($arr, TRUE));
?>

Generates the result:

=== arr is now
array (
  0 => 'test',
  1 => 'last',
  2 => 'next',
)
like image 91
King Skippus Avatar answered Sep 23 '22 00:09

King Skippus