Через некоторое время, не зная, как это сделать правильно, и избегайте дублирования кода в нескольких контроллерах, я искал и снова искал, но не могу найти четкого ответа.
В одном случае, в частности, необходимо рассчитать несколько статистических данных, выполненных над сущностью. Этот расчет будет использоваться в трех разных контроллерах. В двух из них я покажу разбитый на разные макеты, а на третьем я буду использовать эти данные, чтобы сделать глобальный расчет. бизнес-логика для каждого расчета, включает в себя более 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 говорит в вашей ссылке.
DIC в основном помогает управлять «глобальными» объектами. Контроллеры не являются глобальными объектами. Кроме того, контроллер должен быть как можно более тонким. Это в основном клей между вашей моделью и View / Templates. Таким образом, если вам нужно настроить его, это, вероятно, означает, что вам нужно реорганизовать их и извлечь из них бизнес-логику.
Подробнее о 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'); // ... } }
Надеюсь, это поможет вам избежать большого дублирования кода.