我正在开发一个使用REST API后端的应用程序。此API具有登录步骤,该步骤创建用于所有后续API请求的令牌。我将此令牌存储在auth存储中,并且我有一个事件挂钩,用于检查用户是否已登录,如果没有,则呈现登录页面:
$eventManager->attach(MvcEvent::EVENT_ROUTE, function($e) use ($view, $auth) {
$match = $e->getRouteMatch();
// No route match, this is a 404
if (!$match instanceof RouteMatch) {
return;
}
// Route is whitelisted
$matchedRoute = $match->getMatchedRouteName();
if (in_array($matchedRoute, array('login'))) {
return;
}
// if they're logged in, all is good
if ($auth->hasIdentity()) {
return true;
}
[render login form and return response object]
}, -100);
这很有效。
API有时也会以我无法轻易预测的方式过期登录令牌,这意味着所有API调用都将返回“会话过期”类型错误。我在API调用之后写了一个事件触发器,我可以挂钩。我想检查这些“会话过期”响应,并以某种方式呈现登录页面,方法与上面相同:
$events->attach('Api', 'call', function ($e) {
$api = $e->getTarget();
$params = $e->getParams();
$result = $params['apiResult'];
if ([result is a session expired response]) {
// what can I do here?
}
}, 999);
但由于这不是MVC事件,即使我可以在这里访问响应对象,返回它也不会做任何事情。什么是在非MVC事件中中断应用程序流的最佳方法?
答案 0 :(得分:1)
我不确定,但我假设您的API事件确实发生在专用的EventManager
实例中(因此您的API可能是EventManagerAwareInterface
的实现)而不是MVC实例(你从Zend\Mvc\Application
实例中获取的那个。
如果是这种情况,您可以在API中注入主EventManager
和MvcEvent
,然后从call
侦听器中短路MVC周期。
即。假设您的依赖项位于带有getter的$mvcEvent
和$mvcEventManager
属性中,这就是您监听call
事件的方式:
$events->attach('call', function($e) {
$api = $e->getTarget();
$params = $e->getParams();
$result = $params['apiResult'];
if ([result is a session expired response]) {
$mvcEvent = $api->getMvcEvent();
$mvcEvent->setError('api error');
$mvcEvent->setParam('exception', new \Exception('Session expired'));
$api->getMvcEventManager()->trigger('dispatch.error', $mvcEvent);
}
}, 999);
有更好的方法可以做到这一点,选择最佳方式取决于API类的体系结构。
您可以使用触发器返回的Zend\EventManager\ResponseCollection
,而不是在侦听器中使用MVC事件;这将使您的API事件周期继续,即使发生一些错误。这实际上是Zend\Mvc\Application
在run()
方法中使用自己的事件管理器的方式,因此您可以查看示例。