Поймать исключения в Zend Framework 3 - PullRequest
0 голосов
/ 14 октября 2018

Я использую скелетное приложение ZF3.Интересно, где я должен ловить исключения во всем мире?

Пример. Прямо сейчас, если я получаю доступ к недопустимому маршруту (mysite.com/invalid-route), приложение выдает необработанное исключение и код ответа HTTP 200

Неустранимая ошибка: Uncaught Zend \ View \ Exception \ RuntimeException: экземпляр RouteMatch не предоставлен

Я ожидаю, что будет запущена страница ошибки встроенной ошибки 404.

Чего мне не хватает?Может ли кто-нибудь указать мне правильное направление?

Исключение правильно регистрируется с использованием следующего кода:

class Module implements ConfigProviderInterface
{
     const VERSION = '3.0.3-dev';

     public function onBootstrap()
     {
         $logger = new Logger();
         $writer = new Writer\Stream(__DIR__ . '/../../../data/log/error.log');
         $logger->addWriter($writer);

         // Log PHP errors
         Logger::registerErrorHandler($logger, true);

         // Log exceptions
         Logger::registerExceptionHandler($logger);
     }

1 Ответ

0 голосов
/ 15 октября 2018

Это то, что вы можете поймать, используя Listener, запущенный на раннем событии MvcEvent::EVENT_ROUTE.

Я бы предложил использовать выделенный класс и фабрику, чтобы разделить озабоченность по поводу использования функции onBootstrap.Вы могли бы сделать это, зарегистрировав и «активировав» класс Listener, например:

'listeners'       => [
    // This makes sure it "gets listened to" from the very start of the application (onBootstrap)
    RouteExistsListener::class,     
],
'service_manager' => [
    'factories' => [
        // This is just what you think it is
        RouteExistsListener::class  => InvokableFactory::class,
    ],
],

Вы можете использовать только InvokableFactory для этого слушателя, так как особых требований нет.

class RouteExistsListener implements ListenerAggregateInterface
{
    /**
     * @var array
     */
    protected $listeners = [];

    /**
     * @param EventManagerInterface $events
     */
    public function detach(EventManagerInterface $events)
    {
        foreach ($this->listeners as $index => $listener) {
            if ($events->detach($listener)) {
                unset($this->listeners[$index]);
            }
        }
    }

    /**
     * @param EventManagerInterface $events
     */
    public function attach(EventManagerInterface $events, $priority = 1)
    {
        $events->attach(MvcEvent::EVENT_ROUTE, [$this, 'doesRouteExist'], 100);
    }

    /**
     * @param MvcEvent $event
     *
     * @return void|Response
     * @throws Exception
     */
    public function doesRouteExist(MvcEvent $event)
    {
        /** @var TranslatorAwareTreeRouteStack|TreeRouteStack $router */
        $router = $event->getRouter();
        /** @var Request $request */
        $request = $event->getRequest();
        /** @var RouteMatch|null $routeExists */
        $routeExists = $router->match($request); // Return RouteMatch|null

        if ($routeExists instanceof RouteMatch) {
            return; // Route exists - nothing to do
        }

        $url = $router->assemble([], ['name' => 'home']); // Name of your redirect route (ie. not_found/404, or something)

        /** @var Response $response */
        $response = $event->getResponse();
        $response->getHeaders()->addHeaderLine('Location', $url);
        $response->setStatusCode(302);
        $response->sendHeaders();

        $event->getApplication()->getEventManager()->attach(
            MvcEvent::EVENT_ROUTE,
            function (MvcEvent $event) use ($response) {
                $event->stopPropagation();

                return $response;
            },
            -10000
        );

        return $response;
    }
}

ПРИМЕЧАНИЕ: Использовал свой собственный класс для вышеупомянутого и изменил, как я думаю, он должен работать.Тем не менее, может содержать одну или две ошибки ;-) Тем не менее, я думаю, вы должны указать правильное направление.

...