2013-10-30 37 views
1

我正在研究使用REST API后端的应用程序。这个API有一个登录步骤,它创建一个用于所有后续API请求的令牌。我存储此令牌,在身份验证存储,并且我有一个事件钩子检查,如果用户登录,如果没有,呈现登录页面:中断来自非MVC事件的应用程序流

$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调用都将返回'Session expired'类型的错误。我在API调用之后写入了一个事件触发器,可以将其插入。我要检查这些“session过期的回应,不知何故以同样的方式我上面做渲染登录页面:

$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事件中中断应用程序流的最佳方式是什么?

回答

1

我不确定,但我假设您的API事件确实发生在专用的EventManager实例中(因此您的API可能是EventManagerAwareInterface的实现),而不是MVC中的实例(这是您从Zend\Mvc\Application实例)。

如果是这种情况,您可以在API中注入主要的EventManagerMvcEvent,然后从call听众中短接MVC周期。

I.e.假设你的依赖是在$mvcEvent$mvcEventManager属性的getter,这是你将如何监听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\Applicationrun()方法中使用自己的事件管理器的方式,因此您可以在此查看示例。

+0

谢谢,这很有帮助。我通过将MvcEvent和主EventManager传入Api类并触发调度错误来实现您的解决方案,如您的示例中所示。但是这真的只是给了我更多的用户友好的错误信息,我不认为我可以在这里用响应对象做很多事情,所以我可能需要重新思考我的方法。 –

+0

那么使用'dispatch.error'就是一个例子。您可以执行各种操作,即在MvcEvent中设置RouteMatch并触发对您的登录控制器操作的“调度”。 –

相关问题