【问题标题】:Splitting up a Symfony Controller拆分 Symfony 控制器
【发布时间】:2016-01-20 14:07:13
【问题描述】:

我遇到了分解复杂控制器的问题。

动作有许多不同的条件,每个块内的代码使用不同的依赖关系。将其分解为单独的控制器的最合乎逻辑的方法是什么,以便我更好地处理不断增长的构造函数依赖项列表?

这一切都在一个动作中的原因是因为它提供一个 URL /report,它根据权限和其他条件呈现不同的模板。

附言。该代码在技术上不正确,是为了可视化我的问题而快速制作的。

<?php

class ExampleController
{
    protected $dependency1;

    protected $dependency2;

    protected $dependency3;

    protected $user;

    /**
     * ExampleController constructor.
     *
     * @param $dependency1
     * @param $dependency2
     * @param $dependency3
     * @param $user
     */
    public function __construct($dependency1, $dependency2, $dependency3, $user)
    {
        $this->dependency1 = $dependency1;
        $this->dependency2 = $dependency2;
        $this->dependency3 = $dependency3;
        $this->user = $user;
    }

    public function exampleAction()
    {
        if ($this->user->hasRole('a')) {
            $this->dependency1->something();
        } elseif ($this->user->hasRole('b')) {
            $this->dependency2->something();
        } elseif ($this->user->hasRole('c')) {
            $this->dependency3->something();
        }

    }

}

【问题讨论】:

  • 你的控制器已经是服务了吗?您究竟如何将依赖项注入__construct
  • 是的,这就是您如何将依赖项注入到服务容器中定义的任何其他类中。

标签: php symfony controller dependencies


【解决方案1】:

您必须创建一个服务(您在控制器中调用它)来定义您的所有业务逻辑。 控制器应该只拦截一个请求来呈现一个响应。

编辑: 查看官方文档,尤其是Service Container 部分:http://symfony.com/doc/current/book/service_container.html

【讨论】:

  • 可能会考虑在您的答案中添加一些细节,因为它似乎无法解决问题。例如,如何定义另一个服务来解决基于角色的依赖问题?控制器将如何访问服务?
  • 控制器应该注入一个服务,或者应该是ContainerAware;这样,服务就可以独立处理业务逻辑,远离控制器本身
【解决方案2】:

你可以使用的是链。

您需要有人负责处理依赖项。如果你使用 Symfony DI 容器(我知道你这样做),你可以通过服务定义中的标签轻松地将依赖项添加到 Chain 中。

看看这里http://symfony.com/doc/current/components/dependency_injection/tags.html

如果没有帮助,你可以去杀了我 IRL

【讨论】:

    【解决方案3】:

    我不知道一个最好的方法。一些建议:

    1. 恢复使用依赖注入容器作为服务定位器,并根据需要将依赖项从其中拉出。我非常支持将控制器定义为服务并注入依赖项,但有时使用服务定位器最有意义。

    2. 创建一个 kernel.controller 监听器http://symfony.com/doc/current/cookbook/event_dispatcher/event_listener.html 并使用它根据用户角色或您可能拥有的任何其他条件选择容器。这是一个有据可查的方法,尽管它确实在侦听器中隐藏了一些依赖信息。

    3. 扩展 ControllerResolver http://api.symfony.com/2.0/Symfony/Component/HttpKernel/Controller/ControllerResolver.html 并根据角色或其他条件选择控制器。基本上与使用侦听器的方法相同,但有点上游。这可能是最干净的方法,尽管没有很多例子。 Extending Symfony2 Controller Resolver

    【讨论】:

    • 关于第 1 点,您如何对控制器进行单元测试?这是这种方法唯一困扰我的事情。我什至不确定它为什么会困扰我,单元测试控制器似乎是确保控制器给我正确输出的一种脆弱方法。
    • 我不对控制器进行单元测试,只对各种依赖项进行单元测试。方法 1 是编写 S2 控制器的“标准”方式。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多