я имею Symfony проект и внутри этого проекта, у меня есть большой собственный сервис, который огромен и сложен с собственными зависимостями и т.д …
И я хочу создать фасад для этого сервиса с целью использования моего сервиса в controllers
лайк:
$myService = $this->container->get('service_from_my_domain');
Мой вопрос — как внутри моего фасада я могу получить доступ к container
к сервисным зависимостям. Я знаю только 1 способ — это ввести зависимость в сервис в конфиге yaml.
Но есть ли другой способ сделать это? Подобно:
$dependency = Container::getInstance()->get('my_dependency_service');
я обнаружил этот ответ но использование глобальной переменной чувствует себя как в прошлое …
PS: я не хочу внедрять зависимость через конфигурацию yaml (не инжектор конструктора или сеттер), потому что мне не нужен IoC (инверсия контроля) Вот.
ты можешь сделать это
services:
kernel.listener.acme_listener:
class: Acme\AcmeBundle\EventListener\AcmeListener
arguments:
- @service_container
tags:
- { name: kernel.event_listener, event: kernel.controller, method: onKernelController }
ваш слушатель
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
class AcmeListener
{
/**
* @var Container
*/
private $container;
/**
* Constructor
*
* @param Container $container
*/
public function __construct(Container $container)
{
$this->container = $container;
}
public function onKernelController(FilterControllerEvent $event)
{
$this->container->...
}
}
Если вы действительно хотите повеселиться и сделать выход кода, вы можете сделать что-то вроде этого …
Создать Facade
класс, который должен быть инициализирован при запуске приложения. Итак, в app.php
сразу после линии $kernel = new AppKernel('prod', false);
сделать Facade
инициализации:
$kernel->boot();
$container = $kernel->getContainer();
\MyBundle\Facade::init($container);
И вот код для Facade
учебный класс:
<?php
namespace MyBundle;use Symfony\Component\DependencyInjection\ContainerInterface;
class Facade
{
/**
* self|null
*/
private static $instance = null;
/**
* ContainerInterface
*/
private static $myContainer;
/**
* @param ContainerInterface $container
*/
private function __construct(ContainerInterface $container)
{
self::$myContainer = $container;
}
/**
* @param string $serviceId
*
* @return object
* @throws \Exception
*/
public static function create($serviceId)
{
if (null === self::$instance) {
throw new \Exception("Facade is not instantiated");
}
return self::$myContainer->get($serviceId);
}
/**
* @param ContainerInterface $container
*
* @return null|Facade
*/
public static function init(ContainerInterface $container)
{
if (null === self::$instance) {
self::$instance = new self($container);
}
return self::$instance;
}
}
И где бы вам ни понадобился какой-либо сервис, вы создаете его следующим образом:
$service = \MyBundle\Facade::create('my_dependency_service');
Но, если вы спросите меня — я бы создал сервис Facade, в который был бы добавлен контейнер в конструктор.
И у вас был бы какой-то метод для создания сервиса (Facade::create($serviceId)
), что бы запросить контейнер для данного идентификатора услуги.