Symfony2 многоразовые функции в контроллерах

Спустя некоторое время, не зная, как это сделать правильно, и избегая дублирования кода на нескольких контроллерах, я искал и снова искал, но не могу найти четкого ответа.

В одном случае, в частности, необходимо рассчитать несколько статистических данных, заполненных субъектом. Этот расчет будет использовать в 3 разных контроллерах.
В двух из них я покажу разбитые на разные макеты, а в третьих я буду использовать эти данные для глобальных вычислений.
Бизнес-логика для каждого вычисления включает в себя более 100 строк кода, мне пришлось бы утроить в разных контроллерах.

Схема может быть:

  • Расчет полей заполнен «Данные А»
  • Расчет полей заполнен «Данные Б»
  • Расчет полей заполнен «Данные С»

С этими 3 значениями я делаю более поздний общий расчет.

Варианты, которые я мог бы найти:

Есть идеи, как решить этот сценарий?

большое спасибо

1

Решение

Услуги, кажется, очень соответствуют описанному использованию.

Недавно я работал над бухгалтерским решением. Я использовал много сложных алгоритмов, и вскоре у меня были очень длинные методы, даже пытавшиеся оптимизировать код.

Сервисы легко доступны, и их использование может сделать контроллеры намного более сексуальными, легкими и сделать большие методы удобочитаемыми и более удобными в использовании, используя отдельные сервисы, соответствующие определенным действиям.

И их можно использовать в других компонентах, пока присутствует 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 в основном помогает управлять «глобальными» объектами. Контроллеры не являются глобальными объектами. Более того, контроллер должен быть максимально тонким. В основном это связующее звено между вашей моделью и видом / шаблонами. Таким образом, если вам необходимо настроить его, это, вероятно, означает, что вам нужно реорганизовать их и извлечь из них бизнес-логику.

Подробнее о 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');
// ...
}

}

Надеюсь, это поможет вам избежать дублирования кода.

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]