控制器

时间:2016-01-12 18:49:37

标签: php symfony controller reusability

经过一段时间不知道如何正确地做到这一点,并避免在几个控制器中复制代码,我搜索并再次寻找,但找不到明确的答案。

特别是一个案例,需要计算一个实体完成的几个统计数据。该计算将用于3个不同的控制器。 在其中两个中,我将分解为不同的布局,第三个,我将使用此数据进行全局计算。 每次计算的业务逻辑涉及100多行代码,我不得不在不同的控制器中使用三倍。

计划可能是:

  • 计算字段已完成"数据A"
  • 计算字段已完成"数据B"
  • 计算字段已完成"数据C"

使用这3个值,我稍后进行总计算。

我能找到的选项是:

知道如何解决这种情况吗?

非常感谢

1 个答案:

答案 0 :(得分:3)

服务似乎与描述的用法非常相符。

最近,我参与了会计解决方案。我使用了很多复杂的算法,很快就有很长的方法,甚至尝试优化代码。

服务很容易调用,它们的使用可以使控制器更加性感,更轻,并且通过使用与特定操作相对应的独立服务,使大方法可读并且更易于删除。

它们可以在其他组件中使用,只要存在DependencyInjection,如果您需要在控制器的另一个上下文中应用它,它就足以移动您的逻辑。

声明它很简单:

services:
    acmeapp.calculation:
        class: Acme\AppBundle\Services\CalculationService
        arguments: ["@doctrine.orm.entity_manager", "@acmeapp.anotherservice"]

服务

class CalculationService {

    protected $em;
    protected $another;

    public function __constructor(EntityManager $entityManager, AnotherService $anotherService)
    {
        $this->em = $entityManager;
        $this->another = $anotherService;
    }

    //...
}

Controller-Service方法主要是一项服务,具有其所有优点 您的服务方法可以呈现视图并使用_controller属性关联路由,如下所示:

display_data_a:
    path:     /data/A
    methods: GET
    defaults: { _controller: acmeapp.calculation:dealWithData }

不从Symfony\Bundle\FrameworkBundle\Controller\Controller扩展您的服务,当然,您可以使用它。

另外,如果您的控制器之间有许多重复的代码和几个不同的字符,抽象BaseController可能是一个非常干净的选择。
这是我在使用服务之前所做的事情,如果这些方法与我对控制器的定义相对应,这与@fabpot在链接中的内容相对应。

  

DIC主要帮助管理"全球"对象。控制器不是全局对象。而且,控制器应尽可能薄。它主要是模型和视图/模板之间的粘合剂。因此,如果您需要能够自定义,那么可能意味着您需要重构它们并从中提取业务逻辑。

有关OOP中BaseController的更多信息,

方法很简单,如果你有一行代码在方法中重复两到三次,你就使用一个变量。
对于代码块,您将使用一种方法。 对于控制器它是相同的,如果你有两个或多个相同类型的对象(这里是一个控制器),你应该使用一个AbstractController(或BaseController),移动你的重复方法(当然只有一次) ,并从子控制器中删除它们。

BaseController:

class BaseController extends Controller
{
    /**
     * Shortcut for get doctrine entity manager.
     */
    public function getEntityManager()
    {
        return $this->getDoctrine->getEntityManager();
    }

    /**
     * Shortcut for locate a resource in the application.
     */
    public function locateResource($path)
    {
        return $this->get('kernel')->locateResource($path);
    }

    // ...
}

并将其用作子控制器的一部分

class ChildController extends BaseController
{
    public function helloAction()
    {
        $em = $this->getEntityManager();
        $file = $this->locateResource('@AcmeAppBundle/Resources/config/hello.yml');
        // ...
    }

}

希望这可以帮助您避免大量重复的代码。