我使用ZF3骨架应用程序。 我想知道应该在哪里捕获全局异常。
示例: 现在,如果我访问无效的路由(mysite.com/invalid-route),则应用程序报告未捕获的期望和HTTP响应代码200
致命错误:未捕获的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);
}
答案 0 :(得分:0)
这是您可以使用侦听器捕获的,并在早期事件MvcEvent::EVENT_ROUTE
上触发。
我建议使用专用的类和工厂来分隔对onBootstrap
函数使用的关注。您可以通过注册和“激活”一个监听器类来做到这一点,就像这样:
'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;
}
}
注意:将我自己的现有类用于上述内容,并根据我的认为进行了修改。但是,可能包含一个或两个错误;-)仍然,应该指出正确的方向。