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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: contact at jaborandi dot org dot ru
New email:
PHP Version: OS:

 

 [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 15:01:29 2024 UTC