【问题标题】:Decorate general controller actions装饰通用控制器动作
【发布时间】:2015-03-06 17:36:01
【问题描述】:

我想装饰我项目中的每个控制器动作。 我想启动一个自定义记录器引擎并在每次调用操作方法时停止它。

像这样:

class HomeController
{
    public function indexAction() 
    {
         Logger:start();
         someLogicInThere();
         ...
         Logger:end();
    }
}

我想自动扩展到某个类或类似的东西。

我的最终类控制器将如下所示:

class HomeController extends ControllerDecorator
{
    public function indexAction() 
    {
         someLogicInThere();
         ...
    }
}

顺便说一句:记录器的东西并不重要。我的问题更多是设计模式问题

有什么好主意吗?

【问题讨论】:

    标签: php design-patterns decorator


    【解决方案1】:

    您的问题称为Cross-cutting concern。处理此问题的一种方法是通过Aspect-oriented programming

    你可以在 PHP >= 5.4 中使用Traits 伪造这个:

    trait Logger
    {
        public function indexAction()
        {
            echo 'logging before<br>';
    
            parent::indexAction();
    
            echo 'logging after<br>';
        }
    }
    
    class HomeControllerBase
    {
        public function indexAction()
        {
             echo 'indexAction<br>';
        }
    }
    
    class HomeController extends HomeControllerBase
    {
        use Logger;
    }
    
    $homeController = new HomeController();
    $homeController->indexAction();
    

    作为一个实验,我已经自动化了这个编写基类的过程:

    https://github.com/bitworking/AOP

    我不会真正在生产中使用它,因为它需要很多资源。

    更好地研究解析文档类型并缓存新创建的类的 AOP 框架。 未测试:

    http://go.aopphp.com/

    https://github.com/AOP-PHP/AOP

    另一种处理横切关注点的方法是使用event driven programming。这不会像 AOP 那样将其 100% 分开,但它是一种更受认可的设计模式,尤其是在 PHP 中。

    【讨论】:

    • 我不想每次在每个控制器中创建动作时都这样做。顺便说一句,特质想法很棒。我想要更“自动”的东西
    • 好的,如果您需要在每个操作上调用相同的方法,我会考虑编写 controller plugin 并使用 preDispatchpostDispatch 挂钩。
    • here 您会看到一个漂亮的图形,其中包含完整的调度过程。
    • 完全隔离的服务呢?
    • @Mauro 你到底是什么意思?控制器插件是隔离的。
    【解决方案2】:

    您可以在 ControllerDecorator 中使用内置方法 beforeAction (http://www.yiiframework.com/doc/api/1.1/CController#beforeAction-detail) 和 afterAction (http://www.yiiframework.com/doc/api/1.1/CController#afterAction-detail)。 这样您就可以装饰扩展 ControllerDecorator 的每个类。

    ps:我假设您使用的是 Yii。对吧?

    【讨论】:

    • 那我觉得你应该看看这里:framework.zend.com/manual/1.12/en/zend.controller.action.html。特别要注意方法 init()。它充当控制器的每个操作的钩子。这就是您要搜索的内容吗?
    • 这不是一个坏主意(使用前调度和后调度),但在这种方法中,我没有足够的关于调用的实际操作的信息(如方法名称、参数等......) .
    • 在 preDispatch 方法的范围内,$request 对象不可用吗?我从未使用过 ZF,但据我所知,这应该是可以预料到的……我会深入挖掘并尝试找出更多相关信息。
    • @SomethingWicked 就像我写的那样:使用控制器插件,您就可以访问请求对象。
    • public function preDispatch(Zend_Controller_Request_Abstract $request) { $request-&gt;getActionName()) $request-&gt;getParam('param') }
    猜你喜欢
    • 2015-12-03
    • 2023-03-25
    • 2019-07-16
    • 1970-01-01
    • 1970-01-01
    • 2014-07-23
    • 1970-01-01
    • 1970-01-01
    • 2021-05-09
    相关资源
    最近更新 更多