Reputation: 2294
I want to have Psr\Log\LoggerInterface
public in symfony to be able to get it directly from the container with $container->get('Psr\Log\LoggerInterface')
.
I tried the following services.yaml
:
_defaults:
public: true
Psr\Log\LoggerInterface:
public: true
Psr\Log\LoggerInterface:
alias: 'logger'
public: true
Psr\Log\LoggerInterface:
alias: 'monolog.logger'
public: true
I can not get a clue why it is so hard to rewrite a service.
Upvotes: 3
Views: 3112
Reputation: 5734
Not sure if it helps in your case, but in my case I needed a public version of the monolog.logger
service in the tests to mock it. So I created a public alias of it:
test.monolog.logger:
alias: 'Psr\Log\LoggerInterface'
public: true
Now when I inject this service using DI with the LoggerInterface
class I get this service, which I mocked in my test with:
$loggerMock = $this->createMock(LoggerInterface::class);
static::getContainer()->set("test.monolog.logger", $loggerMock);
Upvotes: 0
Reputation: 48865
As previously noted, directly accessing services from the container is discouraged. But I was a bit curious to see how to make a private service public. I tried what was listed in the question and confirmed it did not work.
This may not be the simplest approach but a compiler pass will do the trick:
# src/Kernel.php
# Make the kernel a compiler pass
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
class Kernel extends BaseKernel implements CompilerPassInterface
...
public function process(ContainerBuilder $container)
{
$logger = $container->getAlias(LoggerInterface::class);
$logger->setPublic(true);
}
# And that should do the trick, you can confirm with
bin/console debug:container Psr\Log\LoggerInterface
Be aware that only services which have the complete container injected will be able to take advantage of this. Controllers which extend from AbstractController only have access to a small number of services.
Take a look at Service Subscribers if you need the logger in your controller or if you just want a "better" way of doing this.
Upvotes: 4
Reputation: 1183
Using $container->get() is a bad practise. It violates many good software design principles.
You should use constructor injection instead.
class Foo
{
protected $logger;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
}
Upvotes: -4