【问题标题】:ZF2 Use Redirect in outside of controllerZF2 在控制器外部使用重定向
【发布时间】:2013-06-11 22:51:25
【问题描述】:

我正在开发一个在 Module.php 中调用并附加到引导程序的 ACL。

显然,ACL 限制了对站点某些区域的访问,这就需要重定向。但是,当尝试使用控制器插件进行重定向时,它不起作用,因为插件似乎需要控制器。

从控制器外部重定向到外部的最佳方式是什么? vanilla header() 函数不适合,因为我需要使用已定义的路由。

任何帮助都会很棒!

干杯-

【问题讨论】:

    标签: redirect controller zend-framework2


    【解决方案1】:

    通常,您希望通过返回响应来短路调度过程。在routedispatch 期间,您可以返回响应以停止通常的代码流停止并直接完成结果。如果是 ACL 检查,您很可能希望尽早返回该响应并重定向到用户的登录页面。

    您要么在控制器中构造响应,要么检查插件的返回值并在响应时重定向。注意第二种方法类似于how the PRG plugin works

    第一种方法的例子:

    use Zend\Mvc\Controller\AbstractActionController;
    
    class MyController extends AbstractActionController
    {
        public function fooAction()
        {
            if (!$this->aclAllowsAccess()) {
                // Use redirect plugin to redirect
                return $this->redirect('user/login');
            }
    
            // normal code flow
        }
    }
    

    类似 PRG 插件的例子:

    use Zend\Mvc\Controller\AbstractActionController;
    use Zend\Http\Response;
    
    class MyController extends AbstractActionController
    {
        public function fooAction()
        {
            $result = $this->aclCheck();
    
            if ($result instanceof Response) {
                // Use return value to short-circuit
                return $result
            }
    
            // normal code flow
        }
    }
    

    插件可能看起来像这样(在第二种情况下):

    use Zend\Mvc\Controller\Plugin\AbstractPlugin;
    
    class AclCheck extends AbstractPlugin
    {
        public function __invoke()
        {
            // Check the ACL
            if (false === $result) {
                $controller = $this->getController();
                $redirector = $controller->getPluginManager()->get('Redirect');
                $response = $redirector->toRoute('user/login');
    
                return $response;
            }
        }
    }
    

    在你的问题中你说:

    [...] 它不起作用,因为插件似乎需要控制器。

    当您想在插件中执行$this->getController() 时,这可能是控制器插件内部的问题。您必须扩展 Zend\Mvc\Controller\Plugin\AbstractPlugin 或实现 Zend\Mvc\Controller\Plugin\PluginInterface 以确保您的 ACL 插件被控制器注入。

    如果您不希望这样,可以选择直接返回您自己创建的响应。它有点不太灵活,你在已经有一个响应对象的时候创建一个响应对象(导致两个响应可能发生冲突),但是插件代码会改变如下:

    use Zend\Mvc\Controller\Plugin\AbstractPlugin;
    use Zend\Http\PhpEnvironment\Response;
    
    class AclCheck extends AbstractPlugin
    {
        public function __invoke()
        {
            // Check the ACL
            if (false === $result) {
                $response = new Response;
                $response->setStatusCode(302);
                $response->getHeaders()
                         ->addHeaderLine('Location', '/user/login');
    
                return $response;
            }
        }
    }
    

    【讨论】:

    • 您好,感谢您的详细回复,非常感谢。我已经在一些基本功能上对其进行了测试,在大多数情况下它似乎可以工作,我只是希望它可以在我在另一台机器上拥有的更广泛的功能上工作。再次感谢。
    • 当插件抱怨redirect() 需要控制器时,这是因为acl 插件是从控制器外部调用的,来自Module 类。然后,您建议的常规插件扩展和实现不会为您提供带有 $this->getController() 的控制器。因此,这不是“如果您不想要这个”,而是在这种情况下,您的响应解决方案是唯一的解决方案。
    猜你喜欢
    • 1970-01-01
    • 2014-07-04
    • 1970-01-01
    • 2011-11-23
    • 1970-01-01
    • 2015-02-07
    • 2010-12-05
    • 1970-01-01
    • 2012-04-02
    相关资源
    最近更新 更多