且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Symfony2在控制器中可重用的函数

更新时间:2023-11-17 12:09:34

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



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



服务很容易调用,他们的使用可以使控制器这么多,更轻,并且通过使用对应于特定动作的分开的服务来使得大的方法可读和更容易。



并且它们可以用于其他组件,只要DependencyInjection存在,这是一个足够的理由来移动你的逻辑,如果你可能需要在控制器的另一个上下文中应用它。



很容易声明它:

 服务:
acmeapp.calculation:
类:Acme\AppBundle\Services\CalculationService
参数: @ doctrine.orm.entity_manager,@ acmeapp.anotherservice]

p>

 类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
方法:GET
默认值:{_controller:acmeapp.calculation:dealWithData}

Symfony \Bundle\FrameworkBundle\Controller\Controller ,但是,当然,你可以使用它。



此外,如果您的控制器之间有多个不同字符的复制代码,抽象 BaseController 可能是一个非常干净的替代方法。

这是我在使用服务之前,如果方法对应于我的定义一个控制器,这是对应的@fabpot在你的链接中说的。


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


更多关于OOP中的BaseController,



方法很简单,如果你有一行代码在一个方法中重复两次或三次, 。

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



BaseController:

  class BaseController extends Controller 
{
/ **
*获取doctrine实体管理器的快捷方式。
* /
public function getEntityManager()
{
return $ this-> getDoctrine-> getEntityManager();
}

/ **
*在应用程序中查找资源的快捷方式。
* /
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');
// ...
}

}

希望这有助于避免大量的重复代码。


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. 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.

A scheme could be:

  • Calculation fields completed "Data A"
  • Calculation fields completed "Data B"
  • Calculation fields completed "Data C"

With these 3 values, I make a later total calculation.

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.

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.
A method of your service can render a view and have a route associated using the _controller attribute, like this :

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.

Also, an abstract BaseController can be a very clean alternative, if you have many duplicated code with a few different characters between your controllers.
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.

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.

More about BaseController in OOP,

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.

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.