ZF2如何监听特定控制器的调度事件


ZF2 how to listen to the dispatch event of a specific controller

如何监听特定控制器的调度事件?目前我做以下事情:

Module.php

public function onBootstrap(EventInterface $event) {
    $application = $event->getApplication();
    $eventManager = $application->getEventManager();
    $serviceManager  = $application->getServiceManager();
    $eventManager->attach($serviceManager->get('MyListener'));
}

MyListener.php

class MyListener extends AbstractListenerAggregate {
    public function attach(EventManagerInterface $eventManager) {
        $this->listeners[] = $eventManager->attach(
            MvcEvent::EVENT_DISPATCH, function($event) {
                $this->setLayout($event);
            }, 100
        );
    }
    public function setLayout(EventInterface $event) {
        $event->getViewModel()->setTemplate('mylayout');
    }
}

这设置了所有控制器调度的布局。现在,我只想在应用程序调度特定控制器时设置布局。

与所有模块都有onBootstrap()方法一样,所有扩展AbstractController的控制器都有
onDispatch()方法。

考虑到您想为单个特定控制器应用不同的布局,您可以简单地执行以下操作:

<?php
namespace MyModule'Controller;
use Zend'Mvc'Controller'AbstractActionController; // Or AbstractRestfulController or your own
use Zend'View'Model'ViewModel; // Or JsonModel or your own
use Zend'Mvc'MvcEvent;
class MyController extends AbstractActionController
{
    public function onDispatch(MvcEvent $e)
    {
        $this -> layout('my-layout'); // The layout name has been declared somewhere in your config
        return parent::onDispatch($e); // Get back to the usual dispatch process
    }
    // ... Your actions
}

您可以对每个具有特殊布局的控制器执行此操作。对于那些不写的人,你什么都不用写。

如果您经常需要更改布局(例如,您必须处理的不是单个控制器,而是多个控制器),您可以在module.php中附加MvcEvent,以便在一个位置获取布局设置代码。

为了简单起见,我在这里不使用自定义侦听器,但您也可以使用它。

<?php
namespace MyModule;
use Zend'Mvc'MvcEvent;
class Module
{
    public function onBootstrap(MvcEvent $e)
    {
        $eventManager = $e -> getApplication() -> getEventManager();
        $eventManager -> attach(
            MvcEvent::EVENT_DISPATCH,
            // Add dispatch error event only if you want to change your layout in your error views. A few lines more are required in that case.
            // MvcEvent::EVENT_DISPATCH | MvcEvent::EVENT_DISPATCH_ERROR
            array($this, 'onDispatch'), // Callback defined as onDispatch() method on $this object
            100 // Note that you don't have to set this parameter if you're managing layouts only
        );
    }
    public function onDispatch(MvcEvent $e)
    {
        $routeMatch = $e -> getRouteMatch();
        $routeParams = $routeMatch -> getParams();
        switch ($routeParams['__CONTROLLER__']) {
            // You may use $routeParams['controller'] if you need to check the Fully Qualified Class Name of your controller
            case 'MyController':
                $e -> getViewModel() -> setTemplate('my-first-layout');
                break;
            case 'OtherController':
                $e -> getViewModel() -> setTemplate('my-other-layout');
                break;
            default:
                // Ignore
                break;
        }
    }
    // Your other module methods...
}

您必须将事件侦听器连接到SharedEventManager,并侦听"Zend''Stdlib''DispatchableInterface"接口的MvcEvent::event_DispatchH。

参见示例:

$eventManager->getSharedManager()
            ->attach(
                'Zend'Stdlib'DispatchableInterface',
                MvcEvent::EVENT_DISPATCH,
                $serviceManager->get('MyListener')
            );

在监听器中,您可以获得目标控制器的实例,如so$controller=$event->getTarget();

因此,最终,方法"setLayout"可能看起来像这样:

public function setLayout(MvcEvent $event)
{
    $controller  = $event->getTarget();
    if ($controller instanceof MyController)
    {
        $event->getViewModel()->setTemplate('mycontroller-layout');
    }
}