php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #72326 Closure::call does not allow closure to accept arguments by reference
Submitted: 2016-06-03 10:47 UTC Modified: 2021-12-01 16:09 UTC
Votes:3
Avg. Score:4.3 ± 0.5
Reproduced:3 of 3 (100.0%)
Same Version:2 (66.7%)
Same OS:1 (33.3%)
From: contact at jaborandi dot org dot ru Assigned:
Status: Verified Package: Variables related
PHP Version: 7.0.7 OS:
Private report: No CVE-ID: None
 [2016-06-03 10:47 UTC] contact at jaborandi dot org dot ru
Description:
------------
calling Closure::call() method on anonymouse function that accepts arguments by reference triggers Warning and doesn't execute the function

if same closure is called in regular way, or using call_user_func, or if it does not accept any argument by reference, it is executed normally

tested in 7.0.7, as well as in 7.0.3, 7.0.4, 7.0.5, with the same result

(haven't tested call_user_func in 7.0.5 though, sandbox disabled it)

Test script:
---------------
$a = function(&$arg) { echo "ok"; };
$z = 1;
class MyContext {}
$a->call(new MyContext, $z);

Expected result:
----------------
ok

Actual result:
--------------
Warning: Parameter 1 to MyContext::{closure}() expected to be a reference, value given in C:\bin\php7.0.7\bug.php on line 6

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-06-03 10:51 UTC] contact at jaborandi dot org dot ru
Extra test code, to compare with cases when works:

$a = function($arg) { echo "\nok"; };
$aRef = function(&$arg) { echo "\nok"; };

$z = 1;

$a($z); // ok
$aRef($z); // ok

call_user_func($a, $z); // ok
call_user_func($aRef, $z); // ok

class MyContext {}

$a->call(new MyContext, $z); // ok
$aRef->call(new MyContext, $z); // WARNING ...

Expected:

ok
ok
ok
ok
ok
ok

Actual:

ok
ok
ok
ok
ok
Warning: Parameter 1 to MyContext::{closure}() expected to be a reference, value given in C:\bin\php7.0.7\bug.php on line 17
 [2016-06-03 18:02 UTC] contact at jaborandi dot org dot ru
Obvious workaround, (which I have successfully missed at first, hence this bug report), is to use Closure::bind and then call the function in a regular way.
 [2016-06-03 18:07 UTC] contact at jaborandi dot org dot ru
A misinformation in my original post, call_user_func does not (always) work.
It works only if function was called in a regular way first (something having to do with internal caching I guess?), which was done in my test.

Here's a corrected sample code:

---------------------

$a = function(&$arg) { echo "\nok"; if (isset($this)) echo ', '.get_class($this); echo "\n"; };

$x = 1;
$y = 1;

$a($x); // ok

call_user_func($a, $x); // ok - because $a($x) was previously called
call_user_func($a, $y); // WARNING - because $a($y) was not called

class MyContext {}

$a->call(new MyContext, $x); // WARNING

$a = Closure::bind($a, new MyContext); // workaround

$a($y); // ok, and in desired context
 [2021-12-01 16:09 UTC] cmb@php.net
-Status: Open +Status: Verified
 [2021-12-01 16:09 UTC] cmb@php.net
Confirmed: <https://3v4l.org/SPse9>.  Since there are viable
workarounds available, that might be a documentation problem.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 11:01:30 2024 UTC