listeners[] = $events->attach(MvcEvent::EVENT_DISPATCH, [$this, 'onDispatch']); if (function_exists('zend_monitor_custom_event_ex')) { $this->listeners[] = $events->attach(MvcEvent::EVENT_DISPATCH_ERROR, [$this, 'reportMonitorEvent']); } } /** * Listen to the "dispatch" event * * @return mixed */ public function onDispatch(MvcEvent $e) { if (null !== $e->getResult()) { return; } $routeMatch = $e->getRouteMatch(); $controllerName = $routeMatch instanceof RouteMatch ? $routeMatch->getParam('controller', 'not-found') : 'not-found'; $application = $e->getApplication(); $controllerManager = $this->controllerManager; // Query abstract controllers, too! if (! $controllerManager->has($controllerName)) { $return = $this->marshalControllerNotFoundEvent( $application::ERROR_CONTROLLER_NOT_FOUND, $controllerName, $e, $application ); return $this->complete($return, $e); } try { $controller = $controllerManager->get($controllerName); } catch (InvalidControllerException | InvalidServiceException $exception) { $return = $this->marshalControllerNotFoundEvent( $application::ERROR_CONTROLLER_INVALID, $controllerName, $e, $application, $exception ); return $this->complete($return, $e); } catch (Throwable $exception) { $return = $this->marshalBadControllerEvent($controllerName, $e, $application, $exception); return $this->complete($return, $e); } catch (Exception $exception) { // @TODO clean up once PHP 7 requirement is enforced $return = $this->marshalBadControllerEvent($controllerName, $e, $application, $exception); return $this->complete($return, $e); } if ($controller instanceof InjectApplicationEventInterface) { $controller->setEvent($e); } $request = $e->getRequest(); $response = $application->getResponse(); $caughtException = null; try { $return = $controller->dispatch($request, $response); } catch (Throwable $ex) { $caughtException = $ex; } catch (Exception $ex) { // @TODO clean up once PHP 7 requirement is enforced $caughtException = $ex; } if ($caughtException !== null) { $e->setName(MvcEvent::EVENT_DISPATCH_ERROR); $e->setError($application::ERROR_EXCEPTION); $e->setController($controllerName); $e->setControllerClass($controller::class); $e->setParam('exception', $caughtException); $return = $application->getEventManager()->triggerEvent($e)->last(); if (! $return) { $return = $e->getResult(); } } return $this->complete($return, $e); } public function reportMonitorEvent(MvcEvent $e) { $error = $e->getError(); $exception = $e->getParam('exception'); // @TODO clean up once PHP 7 requirement is enforced if ($exception instanceof Exception || $exception instanceof Throwable) { zend_monitor_custom_event_ex( $error, $exception->getMessage(), 'Laminas Exception', ['code' => $exception->getCode(), 'trace' => $exception->getTraceAsString()] ); } } /** * Complete the dispatch * * @return mixed */ protected function complete(mixed $return, MvcEvent $event) { if (! is_object($return)) { if (ArrayUtils::hasStringKeys($return)) { $return = new ArrayObject($return, ArrayObject::ARRAY_AS_PROPS); } } $event->setResult($return); return $return; } /** * Marshal a controller not found exception event * * @param string $type * @param string $controllerName * @param Throwable|Exception $exception * @return mixed */ protected function marshalControllerNotFoundEvent( $type, $controllerName, MvcEvent $event, Application $application, $exception = null ) { $event->setName(MvcEvent::EVENT_DISPATCH_ERROR); $event->setError($type); $event->setController($controllerName); $event->setControllerClass('invalid controller class or alias: ' . $controllerName); if ($exception !== null) { $event->setParam('exception', $exception); } $events = $application->getEventManager(); $results = $events->triggerEvent($event); $return = $results->last(); if (! $return) { $return = $event->getResult(); } return $return; } /** * Marshal a bad controller exception event * * @param string $controllerName * @param Throwable|Exception $exception * @return mixed */ protected function marshalBadControllerEvent( $controllerName, MvcEvent $event, Application $application, $exception ) { $event->setName(MvcEvent::EVENT_DISPATCH_ERROR); $event->setError($application::ERROR_EXCEPTION); $event->setController($controllerName); $event->setParam('exception', $exception); $events = $application->getEventManager(); $results = $events->triggerEvent($event); $return = $results->last(); if (! $return) { return $event->getResult(); } return $return; } }