0

私のZF2アプリケーションでは、時々LoginRequiredという例外をスローします。私はこの例外をキャッチし、ユーザーをログインページにリダイレクトするために使用したいと思います。私はこれをどのようにするべきですか?ZF2:MVC例外をリッスンしてリダイレクト

通常、エラーはサービスレイヤーによってスローされます。これは通常、ディスパッチ中にスローされますが、レンダリング中にスローされる可能性もあります。これは、サービスレイヤメソッドを呼び出すビューヘルパーが存在するためです(現在のユーザーを取得するなど)。

私は、モジュールのブートストラップ方法を使用して、リスナーをdispatch.errorイベントとrender.errorイベントにアタッチするのは簡単なことだと思います。私はLoginRequired例外のテストを計画していましたが、実際の例外を逃すことはできません。 ($mvcEvent->getResult()->exceptionnullを返します)。

答えて

1

私はリスナー集約の例があります。

違いは、リダイレクトが発生するかどうかを判断するために、リスナーが設定と一致するルート名を使用する点です。 dispatch.errorの間に、$mvcEvent->getParam('exception')を使用してMVCイベントから例外をフェッチして確認することができます。

use ArpAuth\Service\AuthenticationService; 
use ArpAuth\Service\AuthenticationServiceAwareTrait; 
use Zend\Console\Console; 
use Zend\EventManager\EventManagerInterface; 
use Zend\Http\Response; 
use Zend\Mvc\MvcEvent; 
use Zend\Mvc\Router\RouteMatch; 
use Zend\EventManager\AbstractListenerAggregate; 


class NoAuthRedirectStrategy extends AbstractListenerAggregate 
{ 

    protected $whitelistRoutes = []; 
    protected $redirectRoute = 'user/auth/login'; 

    use AuthenticationServiceAwareTrait; 

    public function __construct(AuthenticationService $authenticationService, array $options = []) 
    { 
     $this->authenticationService = $authenticationService; 

     if (! empty($options)) { 
      $this->setOptions($options); 
     } 
    } 


    public function attach(EventManagerInterface $eventManager) 
    { 
     $eventManager->attach(MvcEvent::EVENT_DISPATCH, [$this, 'isAuthenticated'], 1000); 
    } 

    public function isAuthenticated(MvcEvent $event) 
    { 
     $routeMatch = $event->getRouteMatch(); 

     if (Console::isConsole() || ! $routeMatch instanceof RouteMatch) { 
      return; 
     } 

     $serviceManager = $event->getApplication()->getServiceManager(); 
     $currentRoute = $routeMatch->getMatchedRouteName(); 
     $isRemoteApiCall = $serviceManager->get('IsRemoteApiCall'); 

     if ($this->hasWhitelistRoute($currentRoute) || $isRemoteApiCall || $this->authenticationService->hasIdentity()) { 
      return; 
     } 

     $router = $event->getRouter(); 
     /** @var Response $response */ 
     $response = $event->getResponse(); 

     $url = $router->assemble([], ['name' => $this->redirectRoute]); 

     $response->getHeaders()->addHeaderLine('Location', $url); 
     $response->setStatusCode(302); 

     return $response; 
    } 

    public function setRedirectRoute($redirectRoute) 
    { 
     $this->redirectRoute = $redirectRoute; 

     return $this; 
    } 

    public function hasWhitelistRoute($route) 
    { 
     return (! empty($route) && in_array($route, $this->whitelistRoutes)); 
    } 

    public function getWhitelistRoutes() 
    { 
     return $this->whitelistRoutes; 
    } 

    public function setWhitelistRoutes(array $routes) 
    { 
     $this->whitelistRoutes = []; 

     return $this->addWhitelistRoutes($routes); 
    } 

    public function addWhitelistRoutes(array $routes) 
    { 
     foreach($routes as $route) { 
      $this->addWhitelistRoute($route); 
     } 
     return $this; 
    } 

    public function addWhitelistRoute($route) 
    { 
     if (! $this->hasWhiteListRoute($route)) { 
      $this->whitelistRoutes[] = $route; 
     } 

     return $this; 
    } 

    public function setOptions(array $options) 
    { 
     if (isset($options['whitelist']) && is_array($options['whitelist'])) { 
      $this->setWhitelistRoutes($options['whitelist']); 
     } 

     if (isset($options['redirect_route'])) { 
      $this->setRedirectRoute($options['redirect_route']); 
     } 

     return $this; 
    } 
} 
+0

ありがとう。 「例外」がイベントパラメータであったことはどうでしたか?それは本当に役に立ちます。 –

+1

@kimディスパッチコントローラのメインイベントリスナーである[ディスパッチリスナ](https://github.com/zendframework/zend-mvc/blob/master/src/DispatchListener.php#L131)を確認してください。 – AlexP

関連する問題