Zend Framework Inspect Controller类用于docblock标记

时间:2011-09-11 15:19:34

标签: zend-framework plugins controller instance

我想实现一个基于Annotations的Authorization FrontController插件,就像ASP.NET Mvc一样。 我以为我可以编写一个前端控制器插件,并将授权检查添加到Zend Framework提供的一个Hook中。例如:

class My_Controller_Plugin_Authorize extends Zend_Controller_Plugin_Abstract {
    public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request){
        ...
        if($user_is_not_loggedin){
             goSomeWhereElse();
        }
    }
}

class MyFancyController extends Zend_Controller_Action{

   /**
    * @Authorize
    */
    public function secretAction(){
        ...
    }
}

现在,我需要检查实际请求的控制器中的docblock,以确定用户前往的操作是否需要授权。 事实证明并非如此简单:Request Object是唯一传递给Hooks的资源。

我以为我可以通过执行controllerName +“Controller”来构建控制器的类名,但是类没有自动加载,因此找不到它并且代码会崩溃。

任何想法?

2 个答案:

答案 0 :(得分:0)

正如您在对问题的评论中所述,调度员可以访问实际控制器实例 - 而不仅仅是控制器名称

可以访问控制器实例的另一个地方是action helper,它可以访问控制器实例。那么也许是一个带有preDispatch()钩子的动作助手,可以执行基于反射的docblock内省?可能会有一些性能受到影响,因为反射被认为很慢。

但是,一般来说,这听起来像是你想要访问控制,通常使用Zend_Acl处理,然后编写一个利用该ACL对象的控制器插件。除非您确实需要对ACL的docblock注释进行基于反射的检查,否则我将使用ACL /插件方法。

答案 1 :(得分:0)

这是我的解决方案。 @Authorize注释可以在类的顶部或单个方法的顶部工作。 显然可以扩展到ACL检查。

<?php
class Ant_Controller_Plugin_Authorize extends Zend_Controller_Plugin_Abstract {

    public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request){
        $frontController = Zend_Controller_Front::getInstance();
        $dispatcher = $frontController->getDispatcher();
        $controllerClass = $dispatcher->getControllerClass($request);
        $dispatcher->loadClass($controllerClass);
        $reflectionClass = new Zend_Reflection_Class($controllerClass);
        $reflectionMethod = $reflectionClass->getMethod($dispatcher->getActionMethod($request));
        try {
            $authClass = $reflectionClass->getDocblock()->hasTag("Authorize");
        } catch (Exception $e) {
            $authClass = false;
        }
        try{
            $authMethod = $reflectionMethod->getDocblock()->hasTag("Authorize");
        }catch (Exception $e){
            $authMethod = false;
        }

        if($authClass || $authMethod){
            if(!Zend_Auth::getInstance()->hasIdentity()){
                $request->setActionName("login")->setControllerName("Accounts");
                $request->setDispatched(false);
            }
        }
    }
}

然后在application.ini

resources.frontController.plugins.Authorize = "Ant_Controller_Plugin_Authorize"