Symfony2 控制器中的可重用函数

Symfony2 reusable functions in controllers

一段时间后不知道如何正确地做到这一点,避免在多个控制器中重复代码,我反复搜索,但找不到明确的答案。

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

方案可以是:

有了这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 在您的 link.

中所说的相对应

The DIC mostly helps manage "global" objects. Controllers are not global objects. Moreover, a controller should be as thin as possible. It's mainly the glue between your Model and the View/Templates. So, if you need to be able to customize then, it probably means that you need to refactor them and extract the business logic from them.

更多关于 OOP 中的 BaseController,

方法很简单,如果你有一行代码在一个方法中重复了两三次,你就用一个变量。
同样对于一段代码,您将使用一个方法。 对于控制器,它是相同的,如果您有两个或多个相同类型的对象(这里是一个控制器),您应该使用一个 AbstractController(或 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');
        // ...
    }

}

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