PHP Внедрение различных зависимостей в субконтроллеры

Я создаю сайт интрасети с помощью frontcontroller, который вытаскивает запрошенную информацию о приложении из репозитория и выполняет этот субконтроллер. У меня есть проблема: каждое приложение может использовать разные службы с разными параметрами конфигурации, и мне нужно передать эти службы в субконтроллер, не пахнув кодом субконтроллера с конфигурационными материалами. Глядя на приведенный ниже пример, я пытаюсь использовать DI, чтобы передать все, что подходит для нескольких сервисов, общих для всех приложений, но когда у меня много разных сервисов, которые не являются общими для всех приложений, он становится беспорядком конструктора. Поскольку субконтроллеры создаются динамически, я не могу просто передать только зависимости, необходимые для каждого отдельного контроллера.

Я обсуждал сохранение зависимостей в репозитории приложений и вызыв субконтроллеров с информацией, извлеченной из этого, но это все еще не кажется мне правильным. Каков правильный способ сделать это без использования локатора сервисов или других анти-шаблонов?

$appRepository = new AppRepository('username_1', 'password_1', 'etc_1');
$userRepository = new UserRepository('username_2', 'password_2', 'etc_2');

// misc services used by apps
$barrinator = new Barrinator('bar_params');
$bazzinator = new Bazzinator('baz_params');

// example
$params['app_id'] = 'foo';
$params['user_id'] = 'bob';

$frontController = new FrontController($appRepository, $userRepository);
$frontController->execute($params);

class FrontController
{
 protected $appRepository = null;
 protected $userRepository = null;

 public function __construct(********************** $appRepository, *********************** $userRepository)
 {
 $this->appRepository = $appRepository;
 $this->userRepository = $userRepository;
 }

 public function execute($params)
 {
 $app = $this->appRepository->get($params['app_id']);
 $appController = $app->getControllerName();
 $controller = new $appController($this->userRepository);
 $controller->execute($params);
 }
}

abstract class AppAbstract
{
 protected $userRepository = null;

 public function __construct(*********************** $userRepository)
 {
 $this->userRepository = $userRepository;
 }

 abstract public function execute($params);
}

class Foo extends AppAbstract
{
 public function execute($params)
 {
 $user = $this->userRepository->get($params['user_id']);
 // etc.
 }
}

class Bar extends AppAbstract
{
 public function execute($params)
 {
 // halp! how to get barrinator resource
 $bar = $barrinator->get($params['bar_id']);
 }
}
1 ответ

Похоже, вы могли бы использовать некоторую помощь из контейнера DI.

Роль контейнера - это графики объектов сборки. Т.е. контейнер может создавать ваши контроллеры и автоматически вводить их зависимости.

Передний контроллер будет выглядеть так:

class FrontController
{
 protected $container;

 public function __construct(Container $container)
 {
 $this->container = $container;
 }

 public function execute($params)
 {
 $app = $this->appRepository->get($params['app_id']);
 $appController = $app->getControllerName();
 $controller = $this->container->get($appController);
 $controller->execute($params);
 }
}

Я биаизую предложить контейнер (я разрабатываю PHP-DI), но вот список контейнеров: https://gist.github.com/mnapoli/6159681

licensed under cc by-sa 3.0 with attribution.