Edit report at https://bugs.php.net/bug.php?id=52937&edit=1
ID: 52937
Comment by: georgir at gmail dot com
Reported by: mryaggi at hotmail dot com
Summary: call_user_func warning is inappropriate
Status: Open
Type: Bug
Package: Scripting Engine problem
Operating System: Seven
PHP Version: 5.3.3
Block user comment: N
Private report: N
New Comment:
The "workaround" from the last comment is not a good idea, because it can not
be applied generally. If you use call_user_func_array('foo', array(&$b)) when
the function foo takes an argument by copy instead of by reference and modifies
it thinking it doesn't matter, $b will still be modified, which is most
certainly undesired.
Also, the issue is more serious than described in the original post. It affects
call_user_func_array as well as call_user_func, and it is not just a warning
that is given, but the whole function does not get executed. This is actually a
big deal, it can break a lot of programs. A setting to allow execution of the
function in this case would be welcome.
Previous Comments:
------------------------------------------------------------------------
[2011-08-04 02:11:00] lucas at threeamdesign dot com
to work around this problem put the reference in the argument array. e.g.:
function foo(&$bar) {
$bar = 5;
}
$a = 1;
$b = 2;
call_user_func('foo', $a);
call_user_func_array('foo', array(&$b));
var_dump($a, $b);
gives
int(1)
int(5)
------------------------------------------------------------------------
[2010-10-11 11:00:54] mryaggi at hotmail dot com
Ok, I'm going to keep it simple.
You say "[I] have to use call_user_func_array instead".
Please show me how.
Note : I'm just trying to avoid the warning properly.
This would be quite a solution :
call_user_func('ExprectRef', & $p);
call_user_func_array('ExprectRef',array( & $p));
But it's a pity you have to write & TWICE. One in the signature, one in the
call_user_func call.
...it looks so much like the depreciated call-time pass-by-reference.
Don't you think?
------------------------------------------------------------------------
[2010-10-03 00:02:58] [email protected]
You *should* know whether the function takes references; it's part of its
signature.
If it does take references you cannot use call_user_func, and have to use
call_user_func_array instead.
------------------------------------------------------------------------
[2010-09-29 19:31:10] mryaggi at hotmail dot com
Thank you for your quick reply.
You say : "Use call_user_func_array()."
But you can run the test script with call_user_func_array() instad, and still
you will get those warnings.
My point is : when you call call_user_func you have no idea whether the
function called expects references or not (values).
The only solution I see is to always give references to call_user_func*()
For ex:
-----------------
function MY_call_user_func_array($Func,$Args)
{
foreach(array_keys($Args) as $i) { $Args[$i] =& $Args[$i]; }//make it a ref
call_user_func_array($Func,$Args);
}
function test(&$z){ echo "ok : " . $z . "\n";}
$a = 1;
MY_call_user_func_array('test',array($a));
-----------------
And here we are! IT WORKS!
but it I feel like I just learnt how to poo in PHP...
------------------------------------------------------------------------
[2010-09-28 03:13:28] [email protected]
Yes, this may be confusing. The problem is that the level of indirection added
means when the function test() is actually called by the implementation of
call_user_func() via zend_call_function, information about the arguments is
lost. Use call_user_func_array().
Tests 1 and 3 are basically the same. The manual for call_user_func has a note:
«Note that the parameters for call_user_func() are not passed by reference.»
Since call_user_func doesn't receive its parameters by reference, by the time
they reach it, it has no way of knowing if the parameters were sent by
reference or not.
Test 2 is a different matter. But you are actually passing a reference to
test() because zend_call_function() is nice and when you pass a non-reference
to a function that expects a reference and the non-reference has refcount 1, it
converts it into a reference. See
http://lxr.php.net/opengrok/xref/PHP_TRUNK/Zend/zend_execute_API.c#860
Again, this makes sense if you're writing an extension and using
zend_call_function() and passing it a variable you've created. I don't see how
this can be fixed, except by adding something like fci->no_separation that
doesn't create a reference even if the refcount is 1. Not sure if it's worth
the trouble.
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
https://bugs.php.net/bug.php?id=52937
--
Edit this bug report at https://bugs.php.net/bug.php?id=52937&edit=1