Jaquarh
Jaquarh

Reputation: 6693

How to access a global object inside a method closure

I currently have a dependency injection module which allows me to create a factory of objects:

class DiModule
{
    private $Callbacks;

    public function set(
        $foo,
        $bar
    ) {
        $this->Callbacks[$foo] = $bar;
    }

    public function get(
        $foo
    ) {
        return $this->Callbacks[$foo];
    }
}

I then have an event object which stores a method closure and the session that will trigger the event.

class Event
{
    private $Sesh;
    private $Method;

    public function set(
        $sesh = array(),
        $method
    ) {
        $this->Sesh = $sesh;
        $this->Method = $method;
    }

    public function get(
    ) {
        return [$this->Sesh,$this->Method];
    }
}

I then have a listener object which searches the sessions set and triggers the event associated with that object.

class Listener
{
    private $Sesh;
    public function setSesh(
        $foo
    ) {
        $this->Sesh = $foo;
    }

    private $Event;
    public function set(
        $foo,
        Event $event
    ) {
        $this->Event[$foo] = $event;
    }

    public function dispatch(
        $foo
    ) {
        $state = true;

        if(isset($this->Event[$foo]))
        {
            foreach($this->Event[$foo]->get()[0] as $sesh)
            {
                if(!isset($this->Sesh[$sesh]) || empty($this->Sesh[$sesh]))
                {
                    $state = false;
                }
            }
        }

        return ($state) ? [true, $this->Event[$foo]->get()[1]()] : [false, "Event was not triggered."];
    }
}

This is an example of this being executed

$di = new DiModule();

$di->set('L', new Listener());
$di->set('E', new Event());

$di->get('E')->set(['misc'], function () { global $di; return $di; });

$di->get('L')->setSesh(array('misc' => 'active')); // not actual sessions yet
$di->get('L')->set('example', $di->get('E'));
var_dump($di->get('L')->dispatch('example'));

The issue is when I try to access my global $di inside a closure, I have googled this numerous times but cannot find a solution.

Upvotes: 5

Views: 180

Answers (2)

Shira
Shira

Reputation: 6560

The set() and get() methods of your DiModule class seem to have mismatched names / implementations.

The code you posted has these methods:

function get($foo, $bar) { /* ... */ }
function set($foo) { /* ... */ }

It should most likely be:

function get($foo) { /* ... */ }
function set($foo, $bar) { /* ... */ }

To make these mistakes less likely, give your arguments meaningful names (like $key and $value) instead of the generic $foo and $bar. Then it would be easier to spot.

Upvotes: 2

laurent
laurent

Reputation: 90804

You need to use the use keyword to access an outside variable from within a closure.

So this:

$di->get('E')->set(['misc'], function () { global $di; return $di; });

Should be written like this:

$di->get('E')->set(['misc'], function () use ($di) { return $di; });

Upvotes: 4

Related Questions