Я запускаю новое приложение slim 4, а текущие версии slim — это больше просто маршрутизатор, чем фреймворк, и у меня нет di-контейнера из коробки, поэтому я выбираю PHP-DI
в качестве DI-контейнера. А чтобы не описывать каждый контроллер в контейнере и не передавать экземпляр контейнера в контроллеры я использую PHP-DI
autowiring.
Но при таком подходе мне нужно внедрить все зависимости в каждый контроллер, и большинство из этих зависимостей можно повторно использовать всеми контроллерами. Пример:
public function __construct(
Environment $twig,
Messages $flashMessage,
RouteCollectorInterface $routeCollector
)
{
$this->render = $twig;
$this->flashMessage = $flashMessage;
$this->routeCollector = $routeCollector;
}
Есть ли способ создать базовый контроллер, внедрить в него все повторно используемые зависимости, чтобы при DIc
создании/автоподключении каждого нового контроллера все уже внедренные зависимости b-z контроллера расширяли базовый? Кроме того, базовый контроллер, вероятно, должен использовать внедрение методов, иначе мне все равно нужно создать конструктор и передать все инъекции в каждом контроллере базовому контроллеру следующим образом:
public function __construct(
Environment $twig,
CommandBus $commandBus,
Messages $flashMessage,
RouteCollectorInterface $routeCollector
)
{
parent::__construct($twig, $flashMessage, $routeCollector);
$this->commandBus = $commandBus;
}
что, вероятно, то же самое, что внедрять зависимости в каждый контроллер вообще без базового контроллера.
Я попытался настроить базовый контроллер:
$definitions[BaseController::class] = static function(ContainerInterface $container): BaseController {
/** @var BaseController $controller */
$controller =new BaseController();
$controller->setView($container->get(Environment::class));
$controller->setRouter($container->get(RouteCollectorInterface::class));
$controller->setFleshMessage($container->get(Messages::class));
return $controller;
};
но это не работает, и зависимости null
для каждого контроллера, расширяющего базовый контроллер.
PHP-DI
http://php-di.org/doc/best-practices.html#writing-controllers предлагают использовать внедрение свойств, но для меня это все еще выглядит как шаблон для внедрения всех повторно используемых внедрений для каждого контроллера, и это нарушает инкапсуляцию, когда мы внедряем в частные свойства.
Одно из решений, которое я могу придумать, состоит в том, чтобы сделать что-то вроде ControllerHelper
со всеми повторно используемыми зависимостями в качестве моста/оболочки и внедрить его вместо всех этих зависимостей, это уменьшит количество дублированного кода. Но все же, может есть лучшее решение???
Обновлено: я знаю, что на самом деле это работает в ООП, если вы расширяете базовый класс, вам нужно передать ему все зависимости. Но чтобы уменьшить некоторое дублирование, здесь было бы неплохо немного магии :) также это не внешний пакет, который будет использоваться кем-то другим, так что, вероятно, такая магия допустима, если ее вообще можно как-то достичь.
Обновлено: другими словами, я пытаюсь добиться следующего:
class SomeController extends BaseController {
// in this case constructor is empty
public function index(RequestInterface $request, ResponseInterface $response) {
return $this->render($response, $templateName, [somedata]);
}
}
где $this-render
— это метод класса BaseController
, который использует зависимость механизма шаблонов для рендеринга представления:
public function render(ResponseInterface $request, string $templateName, array $data): ResponseInterface {
$response->getBody()->write(
$this->render->render(
$templateName,
$data
)
);
return $response;
}
как видите, я не хочу внедрять зависимости в SomeController
, но каким-то образом внедряю их один раз в BaseController