I have symfony project and inside this project, I have big own service which is huge and complicated with own dependencies etc... And I wanna create facade for this service with purpose to use my service in controllers
like:
$myService = $this->container->get('service_from_my_domain');
My question - is how inside my facade I can get access to container
to service's dependencies. I know only 1 way - is to inject dependency into service in yaml config.
But is there another way to do it? Like:
$dependency = Container::getInstance()->get('my_dependency_service');
I've found this answer but using global variable feels like back in time...
PS: I don't want to inject dependency through yaml config (not constructor injection nor setter injection) because I don't need IoC ( inversion-of-control ) here.
can you do like this
services:
kernel.listener.acme_listener:
class: Acme\AcmeBundle\EventListener\AcmeListener
arguments:
- @service_container
tags:
- { name: kernel.event_listener, event: kernel.controller, method: onKernelController }
your Listener
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->...
}
}
If you really want to have a fun and do code escapades, you could do something like this...
Create a Facade
class, that must be initialized when the app starts. So, in app.php
, just after the line $kernel = new AppKernel('prod', false);
do the Facade
initialization:
$kernel->boot();
$container = $kernel->getContainer();
\MyBundle\Facade::init($container);
And, here is a code for the Facade
class:
<?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;
}
}
And, wherever you need some service, you create it this way:
$service = \\MyBundle\\Facade::create('my_dependency_service');
But, if you ask me - I would create a Facade service, that would have a container injected in the constructor. And you would have some method for service creation ( Facade::create($serviceId)
), that would ask the container for given service ID.
I've built a console app using Symfony 5.
Injecting a service in Symfony 5 is as simples as __construct(ServiceClass $service_name)
( type-hinting ) and everything is a service. But in one case I could not dependency inject at the constructor because the dependency service is conditioned to the parameters given at the command line.
So this is how I injected the needed service on the fly.
<?php
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use App\Kernel;
class MyCommand extends Command {
protected static $defaultName = 'app:my-command';
private $container;
public function __construct(Kernel $kernel) {
$this->container = $kernel->getContainer();
//...
parent::__construct();
}
protected function configure() {
// ...
}
protected function execute(InputInterface $input, OutputInterface $output) {
//...
// read the parameters given in the cmd and decide what class is
// gona be injected.
// $service_name = "App\\My\\Namespace\\ServiceClassName"
$service = $this->container->get($service_name);
$service->doSomething();
return Command::SUCCESS;
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.