I\'m creating a wrapper function around mysqli so that my application needn\'t be overly complicated with database-handling code. Part of that is a bit of code to parameter
Adding the &
in the argument signature fixed it for me. This means the function will receive the memory address of the original array.
function setArray(&$vals) {
// ...
}
CodePad.
Pass the array as a reference:
function setArray(&$vals) {
foreach ($vals as $key => &$value) {
$this->myarray[] =& $value;
}
$this->dumpArray();
}
My guess (which could be wrong in some details, but is hopefully correct for the most part) as to why this makes your code work as expected is that when you pass as a value, everything's cool for the call to dumpArray()
inside of setArray()
because the reference to the $vals
array inside setArray()
still exist. But when control returns to myfunc()
then that temporary variable is gone as are all references to it. So PHP dutifully changes the array to string values instead of references before deallocating the memory for it. But if you pass it as a reference from myfunc()
then setArray()
is using references to an array that lives on when control returns to myfunc()
.
I just encountered this same problem in almost exactly the same situation (I'm writing a PDO wrapper for my own purposes). I suspected that PHP was changing the reference to a value once no other variables were referencing the same data, and Rick, your comments in the edit to your question confirmed that suspicion, so thank you for that.
Now, for anybody else who comes across something like this, I believe I have the simplest solution: simply set each relevant array element to a reference to itself before passing the array to call_user_func_array().
I'm not sure exactly what happens internally because it seems like that shouldn't work, but the element becomes a reference again (which you can see with var_dump()), and call_user_func_array() then passes the argument by reference as expected. This fix seems to work even if the array element is still a reference already, so you don't have to check first.
In Rick's code, it would be something like this (everything after the first argument for bind_param is by reference, so I skip the first one and fix all of the ones after that):
for ($i = 1, $count = count($this->bindArgs); $i < $count; $i++) {
$this->bindArgs[$i] = &$this->bindArgs[$i];
}
call_user_func_array(array($stmt, 'bind_param'), $this->bindArgs);