Jon Skarpeteig
Jon Skarpeteig

Reputation: 4128

Using reference in overloaded function using __call()

class a
{
    public function f(&$ref1, &$ref2)
    {
        $ref1 = 'foo';
        $ref2 = 'bar';
    }
}

class b
{
    public function __call($methodName, $arguments)
    {
        $a = new a();
        call_user_func_array(array(
            $a, $methodName
        ), $arguments);
    }
}

$ref1 = 'X';
$ref2 = 'Y';
$b = new b();
$b->f($ref1, $ref2);
var_dump($ref1, $ref2);

This results in:

PHP Warning:  Parameter 1 to a::f() expected to be a reference, value given in /home/jon/sync_workspace/bugsync/tests/test.php on line 18
PHP Stack trace:
PHP   1. {main}() /test.php:0
PHP   2. b->f() /test.php:23
PHP   3. b->__call() /test.php:23
PHP   4. call_user_func_array() /test.php:17
string(1) "X"
string(1) "Y"

How can I accomplish the above in PHP 5.4 (manipulate ref1 and ref2 by use of reference)?

In PHP 5.3 I used the & syntax at $b->f(&$ref1, &$ref2); (even though it's deprecated), but in PHP5.4 this throws fatal error.

Upvotes: 4

Views: 648

Answers (2)

nickb
nickb

Reputation: 59699

I take it back, this is in fact possible, using an array of references. Here is the complete code that I used:

class b
{
    public function __call($methodName, $arguments)
    {
        $a = new a();
        call_user_func_array(array(
            $a, $methodName
        ), $arguments[0]);
    }
}
$ref1 = 'X';
$ref2 = 'Y';
$b = new b();
$b->f( array( &$ref1, &$ref2));
var_dump($ref1, $ref2);

This outputs:

string(3) "foo"
string(3) "bar"

Just as expected, with no warnings or notices.

Upvotes: 0

Jon Skarpeteig
Jon Skarpeteig

Reputation: 4128

I managed to find a solution, although it's a hack.

You can still store references in an array, and pass the array as an argument, which will survive through __call()

class b
{
    public function __call($methodName, $arguments)
    {
        $a = new a();
        call_user_func_array(array(
            $a, $methodName
        ), reset($arguments));
    }
}
$ref1 = 'X';
$ref2 = 'Y';
$b = new b();
$b->f(array(&$ref1, &$ref2));

PHP manual states: Function definitions alone are enough to correctly pass the argument by reference. (http://php.net/manual/en/language.references.pass.php) which clearly isn't the case for __call() referenced functions!

Upvotes: 6

Related Questions