Andy Lobel
Andy Lobel

Reputation: 3416

PHP: Inserting a reference into an array?

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?

Upvotes: 7

Views: 6340

Answers (4)

Akshay Goyal
Akshay Goyal

Reputation: 951

Here I am iterating an array($values_arr) and storing the references of each variable in another array ($params). You can alter the usage it as per your requirements.

$params = array();
$values_arr = array('a', 'b', 123);
foreach ($values_arr as $key=>&$val) {
    $params[$key] = &$val;
}

Result

array (size=3)
  0 => &string 'a' (length=1)
  1 => &string 'b' (length=1)
  2 => &int 123

Upvotes: 0

King Skippus
King Skippus

Reputation: 3826

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',
)

Upvotes: 8

Travesty3
Travesty3

Reputation: 14479

When I try an example like yours, I get a warning that says "Call-time pass-by-reference has been deprecated." According to this answer:

You can set allow_call_time_pass_reference to true in your php.ini file. But it's a hack.

Upvotes: 2

Tyler Carter
Tyler Carter

Reputation: 61567

You might need to make the last argument an array, otherwise according to the manual you'll get typecasted to one.

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

Upvotes: 2

Related Questions