简体   繁体   English

Symfony2在控制器中可重用的功能

[英]Symfony2 reusable functions in controllers

After some time without knowing how to do this properly, and avoid duplicating code in several controllers, I searched and again to seek, but can not find a clear answer. 经过一段时间不知道如何正确地做到这一点,并避免在几个控制器中重复代码,我搜索并再次寻求,但无法找到一个明确的答案。

One case in particular, need to calculate several statistics data completed of an entity. 特别是一个案例,需要计算一个实体完成的几个统计数据。 This calculation will use in 3 different controllers. 该计算将用于3个不同的控制器。 In two of them, I'll show broken down into different layouts, and on the third, I will use this data to make a global calculation. 在其中两个中,我将展示分解为不同的布局,在第三个,我将使用此数据进行全局计算。 business logic for each calculation, involves more than 100 lines of code, I would have to triple in the different controllers. 每次计算的业务逻辑,涉及超过100行代码,我将不得不在不同的控制器中三倍。

A scheme could be: 一个计划可能是:

  • Calculation fields completed "Data A" 计算字段完成“数据A”
  • Calculation fields completed "Data B" 计算字段完成“数据B”
  • Calculation fields completed "Data C" 计算字段完成“数据C”

With these 3 values, I make a later total calculation. 使用这3个值,我稍后进行总计算。

The options that I could find are: 我能找到的选项是:

Any idea how to solve this scenario? 知道如何解决这个问题吗?

thanks a lot 非常感谢

The Services seem to be much corresponding with the described usage. 服务似乎与描述的用法非常相符。

Recently, I worked on an accounting solution. 最近,我参与了会计解决方案。 I used a lot of complex algorithms and I soon had very long methods, even trying to optimise code. 我使用了很多复杂的算法,很快就有很长的方法,甚至尝试优化代码。

Services are easily callable, and their usage can make controllers so much sexier, lighter, and make big methods readable and more cuttable by using separated services corresponding to specific actions. 服务很容易调用,并且它们的使用可以使控制器更加性感,更轻,并且通过使用与特定操作相对应的分离服务使大方法可读并且更可裁剪。

And they can be used in other components, as long as DependencyInjection is present, it's a sufficient raison to move your logic if you may need apply it in another context that a controller. 并且它们可以在其他组件中使用,只要存在DependencyInjection,如果您可能需要在控制器的另一个上下文中应用它,那么移动逻辑就足够了。

It's simple to declare it : 声明它很简单:

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

And the service 和服务

class CalculationService {

    protected $em;
    protected $another;

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

    //...
}

The Controller-Service approach is primarily a service, with all its advantages. Controller-Service方法主要是一种服务,具有其所有优点。
A method of your service can render a view and have a route associated using the _controller attribute, like this : 您的服务方法可以呈现视图并使用_controller属性关联路由,如下所示:

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

Without extending your service from the Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller , but, of course, you can use it. 不从Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller扩展您的服务,但是,当然,您可以使用它。

Also, an abstract BaseController can be a very clean alternative, if you have many duplicated code with a few different characters between your controllers. 此外,如果您的控制器之间有许多重复的代码和几个不同的字符,抽象的BaseController可能是一个非常干净的选择。
It's what I'm doing before use services, if the methods are corresponding with my definition of a controller, which is corresponding to what @fabpot says in your link. 这是我在使用服务之前所做的事情,如果这些方法与我对控制器的定义相对应,这与@fabpot在你的链接中所说的相对应。

The DIC mostly helps manage "global" objects. DIC主要帮助管理“全局”对象。 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. 因此,如果您需要能够自定义,那么可能意味着您需要重构它们并从中提取业务逻辑。

More about BaseController in OOP, 有关OOP中BaseController的更多信息,

The way is simple, if you have a line of code that repeats itself two or three times in a method, you use a variable. 方法很简单,如果你有一行代码在方法中重复两到三次,你就使用一个变量。
Same for a block of code, you will use a method. 对于代码块,您将使用一种方法。 For controllers it's the same, if you have two or more objects of the same type (here a controller), you should use an AbstractController (or BaseController), move your duplicated methods in it (only once, of course), and remove them from the child controllers. 对于控制器它是相同的,如果你有两个或多个相同类型的对象(这里是一个控制器),你应该使用一个AbstractController(或BaseController),移动你的重复方法(当然只有一次),并删除它们来自儿童控制器。

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);
    }

    // ...
}

And use it as part of your child controllers 并将其用作子控制器的一部分

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

}

Hope this helps you to avoid a lot of a duplicated code. 希望这可以帮助您避免大量重复的代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM