Req #71256 [Opn->Wfx]: Magic __call() method should provide references as arguments.
| From: | nikic@php.net | Date: | Wed, 08 Jan 2020 16:10:07 +0000 |
| Subject: | Req #71256 [Opn->Wfx]: Magic __call() method should provide references as arguments. | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-224785@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=71256&edit=1
ID: 71256
Updated by: nikic@php.net
Reported by: toolrulez at gmail dot com
Summary: Magic __call() method should provide references as
arguments.
-Status: Open
+Status: Wont fix
Type: Feature/Change Request
Package: Class/Object related
Operating System: all
PHP Version: Irrelevant
Block user comment: N
Private report: N
New Comment:
I'll go ahead and put this feature request out of it's misery by saying that we will not
implement this.
The fundamental problem is that we need to decided whether an argument needs to be passed by-value
or by-reference when the call is made, and we just don't have the information at that point.
Always passing by-reference is not an option, because it has multiple very undesirable side-effects:
First, it will not generate a warning when passing an undefined variable. Second, it will initialize
the variable (or array offset or object property etc) to null if it isn't initialized already.
And third, it will create a reference structure allocation, which has a significant performance and
memory usage impact.
As always, I recommend to avoid the use of references.
Previous Comments:
------------------------------------------------------------------------
[2019-08-21 13:15:36] nikic@php.net
Related To: Bug #78433
------------------------------------------------------------------------
[2016-01-02 08:59:32] toolrulez at gmail dot com
...And happy new year to you all. :)
------------------------------------------------------------------------
[2015-12-31 15:25:02] toolrulez at gmail dot com
Description:
------------
In PHP 7 (and all previous versions),
there is no elegant way to make the __call magic method work properly with methods that use
parameters by reference.
In php 5.4, the directive "Call-time pass-by-reference" was removed, which is a good thing
since it wasn't very clean.
But it provided a way to make __call arguments work with pass-by-reference functions.
So, in order to make things work more intuitively, I suggest that __call should provide an array of
arguments references instead of an array of copies.
With this, it would be possible to modify the contents of a variable passed as a parameter through
the __call magic method.
--- Notes
Please note that I'm aware of the fact that objects are always passed by reference and that, if
an object was passed as $data in the example below, things would work as expected.
But abjects are not always the most effective way to go (and that it is not always possible to use
them when the __call method is used as a pattern to refactor code).
Also, please note that there is a trick to make this "work" as expected. The trick would
be to pass an array of explicit references to the method doSomthing and then process the array
inside the __call method to give the right array to call_user_func_array.
But this technique would require you to know, from the outside of class A, that this specific __call
method will be used and that it works exacltly like described, which is not the appropriate way to
use objects (i.e. as a blackbox doing things internally that we -the users of that object- are not
necessarily interested in or aware of).
Test script:
---------------
<?php
Class A
{
public function __call($method, $args)
{
call_user_func_array(array($this, $method), $args);
}
// Pass by reference here.
// we expect data to change outside this scope.
protected function doSomethingTo(&$data)
{
$data = "done";
}
}
$data = 42;
$object = new A();
$object->doSomethingTo($data);
var_dump($data);
Expected result:
----------------
string(4) "done"
Actual result:
--------------
Warning: Parameter 1 to A::doSomethingTo() expected to be a reference, value given in /in/GhZii on
line 7
int(42)
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=71256&edit=1