Zend Framework 2 のイベントのリスナをログる

Zend Framework のスケルトンアプリケーションで普通にページを表示したときに発生するイベントの、そのイベントにアタッチされているリスナをログってみました。

## 方法

application.config.php の service_manager で SharedEventManager のファクトリを次のように設定します。

```php:application.config.php
    // ...snip...

    'service_manager' => array(
        'invokables' => array(
            'SharedEventManager' => null,
        ),
        'factories' => array(
            'SharedEventManager' => function(){
                $em = new \Zend\EventManager\SharedEventManager();
                $em->attach('*', '*', function (\Zend\EventManager\EventInterface $ev) {
                    $target = is_object($ev->getTarget()) ? get_class($ev->getTarget()) : $ev->getTarget();
                    $log = sprintf("%-20s%-40s%s", $ev->getName(), $target, get_class($ev));
                    error_log($log);

                    $target = $ev->getTarget();
                    if (!$target instanceof \Zend\EventManager\EventManagerAwareInterface) {
                        error_log("??? unknown target class");
                    } else {
                        $events = $target->getEventManager();
                        foreach ($events->getListeners($ev->getName()) as $listener) {
                            if (!$listener instanceof \Zend\Stdlib\CallbackHandler) {
                                error_log("??? unknown listener class");
                            } else {
                                $priority = $listener->getMetadatum('priority');
                                $priority = var_export($priority, true);

                                $callback = $listener->getCallback();
                                if (is_array($callback)) {
                                    list ($cls, $mem) = $callback;
                                    if (is_object($cls)) {
                                        $cls = get_class($cls);
                                    }
                                    error_log(sprintf("%-20s  %s::%s [%s]", "", $cls, $mem, $priority));
                                } else if (is_object($callback)) {
                                    error_log(sprintf("%-20s  %s [%s]", "", get_class($callback), $priority));
                                } else {
                                    error_log(sprintf("%-20s  %s [%s]", "", "unknown", $priority));
                                }
                            }
                        }
                    }
                    error_log("");
                }, PHP_INT_MAX);

                return $em;
            },
        ),
    ),

    // ...snip...
```

## 結果

IndexController の indexAction で例外を投げたときの結果です（見難かったので手で整形しています）。

インデントの無い行は「イベント名」です。後続するインデント４の行が「ターゲットのクラス」と「イベントオブジェクトのクラス」です。

その後のインデント８の行がイベントにアタッチされていたリスナーです。ブラケットの部分はプライオリティです。

```text
loadModule
    Zend\ModuleManager\ModuleManager
    Zend\ModuleManager\ModuleEvent
        Zend\ModuleManager\Listener\AutoloaderListener [9000]
        Zend\ModuleManager\Listener\ModuleDependencyCheckerListener [8000]
        Zend\ModuleManager\Listener\InitTrigger [1]
        Zend\ModuleManager\Listener\OnBootstrapListener [1]
        Zend\ModuleManager\Listener\LocatorRegistrationListener::onLoadModule [1]
        Zend\ModuleManager\Listener\ConfigListener::onLoadModule [1]
        Zend\ModuleManager\Listener\ServiceListener::onLoadModule [1]

mergeConfig
    Zend\ModuleManager\ModuleManager
    Zend\ModuleManager\ModuleEvent
        Zend\ModuleManager\Listener\ConfigListener::onMergeConfig [1000]

loadModules.post
    Zend\ModuleManager\ModuleManager
    Zend\ModuleManager\ModuleEvent
        Zend\ModuleManager\Listener\ServiceListener::onLoadModulesPost [1]

bootstrap
    Zend\Mvc\Application     
    Zend\Mvc\MvcEvent
        Zend\Mvc\View\Http\ViewManager::onBootstrap [10000]

route
    Zend\Mvc\Application
    Zend\Mvc\MvcEvent
        Zend\Mvc\RouteListener::onRoute [1]
        Zend\Mvc\ModuleRouteListener::onRoute [1]

dispatch
    Zend\Mvc\Application
    Zend\Mvc\MvcEvent
        Zend\Mvc\DispatchListener::onDispatch [1]
        Zend\Mvc\View\Http\RouteNotFoundStrategy::prepareNotFoundViewModel [-90]

dispatch
    Application\Controller\IndexController
    Zend\Mvc\MvcEvent
        Application\Controller\IndexController::onDispatch [1]

dispatch.error
    Zend\Mvc\Application
    Zend\Mvc\MvcEvent
        Zend\Mvc\View\Http\RouteNotFoundStrategy::detectNotFoundError [1]
        Zend\Mvc\View\Http\RouteNotFoundStrategy::prepareNotFoundViewModel [1]
        Zend\Mvc\View\Http\ExceptionStrategy::prepareExceptionViewModel [1]
        Zend\Mvc\View\Http\InjectViewModelListener::injectViewModel [-100]

render
    Zend\Mvc\Application
    Zend\Mvc\MvcEvent
        Zend\Mvc\View\Http\DefaultRenderingStrategy::render [-10000]

render.error
    Zend\Mvc\Application
    Zend\Mvc\MvcEvent
        Zend\Mvc\View\Http\ExceptionStrategy::prepareExceptionViewModel [1]
        Zend\Mvc\View\Http\InjectViewModelListener::injectViewModel [-100]
        Zend\Mvc\View\Http\DefaultRenderingStrategy::render [-10000]

renderer
    Zend\View\View
    Zend\View\ViewEvent
        Zend\View\Strategy\PhpRendererStrategy::selectRenderer [NULL]

renderer.post
    Zend\View\View
    Zend\View\ViewEvent

renderer
    Zend\View\View
    Zend\View\ViewEvent
        Zend\View\Strategy\PhpRendererStrategy::selectRenderer [NULL]

renderer.post
    Zend\View\View
    Zend\View\ViewEvent

response
    Zend\View\View
    Zend\View\ViewEvent
        Zend\View\Strategy\PhpRendererStrategy::injectResponse [NULL]

finish
    Zend\Mvc\Application
    Zend\Mvc\MvcEvent
        Zend\Mvc\SendResponseListener::sendResponse [-10000]

sendResponse
    Zend\Mvc\SendResponseListener
    Zend\Mvc\ResponseSender\SendResponseEvent
        Zend\Mvc\ResponseSender\PhpEnvironmentResponseSender [-1000]
        Zend\Mvc\ResponseSender\ConsoleResponseSender [-2000]
        Zend\Mvc\ResponseSender\SimpleStreamResponseSender [-3000]
        Zend\Mvc\ResponseSender\HttpResponseSender [-4000]
```