matt richards matt richards - 1 month ago 15
PHP Question

php variable reference within closure

I'm having trouble passing a reference around a closure:

class stdobject {
public function __call($method, $arguments) {
if (isset($this->{$method}) && is_callable($this->{$method})) {
return call_user_func_array($this->{$method}, $arguments);
} else {
throw new Exception("Fatal error: Call to undefined method: $method");
}
}
}

$mod=function(){
$test=new stdobject();

$mode;

$test->init=function($params) use (&$mode) {
$mode =& $params['opmode'];
};

$test->setup=function() use (&$mode) {
$mode='test';
};

return $test;
};

$opmode='helloworld';

$test=$mod();
$test->init([ 'opmode' => &$opmode ]);

$test->setup();

echo $opmode; //should display test


I would like the setup function to modify
$opmode
in the outside scope, which would possibly not be the global scope, can anyone point me in the right direction on how to achieve this?

Answer

I am not sure why you would want this, but I guess this is what you were trying to achieve:

class stdobject {
    public function __call($method, $arguments) {    
        if (isset($this->{$method}) && is_callable($this->{$method})) {
            return call_user_func_array($this->{$method}, $arguments);
        } else {
            throw new Exception("Fatal error: Call to undefined method: $method");
        }
    }
}

$mod = function() {
    $self = new stdobject();

    $self->init = function ($params) use ($self) {
        $self->_opmode = &$params['opmode'];
    };

    $self->setup = function () use ($self) {
       $self->_opmode = 'dog';
    };

    $self->print = function () use ($self) {
        echo $self->_opmode . "\n";
    };

    return $self;
};

$obj = $mod();

$reference = 'fish';

$obj->init(['opmode' => &$reference]);
$obj->print();  // fish

$obj->setup();
$obj->print();  // dog

$reference = 'cats';
$obj->print();  // cats

https://3v4l.org/SLAri

However I prefer this:

<?php
class Mod {
    private $opmode;

    public function init($params)
    {
        $this->opmode = &$params['opmode'];
    }

    public function setup()
    {
        $this->opmode = 'dog';
    }

    public function print()
    {
        echo $this->opmode . "\n";
    }

}

$obj = new Mod();

$reference = 'fish';
$obj->init(['opmode' => &$reference]);
$obj->print();  // fish

$obj->setup();
$obj->print();  // dog

$reference = 'cats';
$obj->print();  // cats

https://3v4l.org/T9qr2