Search code examples
phpevent-handlingzend-framework2closures

How to move listener code from closure to method and pass arguments to it in ZF2?


I have a Module class with multiple "inline" event listeners in its onBootstrap(...):

...
class Module
{
    public function onBootstrap(MvcEvent $mvcEvent)
    {
        ...
        $foo = ...;
        ...
        $halPlugin = $viewHelperManager->get('Hal');
        $halPlugin->getEventManager()->attach('bar', function ($event) {
            ...
        });
        ...
        $halPlugin->getEventManager()->attach('baz', function ($event) use ($foo)
        {
            ...
        });
        ...
    }
    ...
}

Now, in order to hold/make Module#onBootstrap(...) slim, I want to move the listeners from the closures to separate methods. It's no problem for the onBar event listener. But it doesn't work for onBaz, that needs additional input:

...
class Module
{
    public function onBootstrap(MvcEvent $mvcEvent)
    {
        ...
        $halPlugin->getEventManager()->attach('bar', [$this, 'onBar']);
        ...
    }
    ...
    public function onBar()
    {
        ...
    }
    public function onBaz() // <-- How to pass $foo to the method?
    {
        // Some stuff, that needs $foo...
        ...
    }
}

In the original variant this input was being passed into the closure via the use directive. But how to do this now?

How to move the logic of an event listener (attached in the Module#onBootstrap(...)) from a closure with a use statement to a separate method and pass arguments to it?


Solution

  • What you can do is move the foo as property of your module class and then access it with $this->foo

    class Module
    {
        private $foo;
    
        public function onBootstrap(MvcEvent $mvcEvent)
        {
            $this->foo = ...;
            $halPlugin->getEventManager()->attach('baz', [$this, 'onBaz']);
            ...
        }
        ...
        public function onBaz()
        {
            $this->foo
            // Some stuff, that needs $foo...
            ...
        }
    }
    

    You can also make the function in module return a Closure where you use $foo sent in with the function.

    class Module
    {
        public function onBootstrap(MvcEvent $mvcEvent)
        {
            $foo = ...;
            $halPlugin->getEventManager()->attach('baz', $this->onBaz($foo));
            ...
        }
        ...
        public function onBaz($foo)
        {
            return function ($event) use ($foo) {
                $this->foo
                // Some stuff, that needs $foo...
                ...
            }
        }
    }