I’m using PHP traits as mixins to inject optional services, i.e.
trait Logger { private LoggerInterface $logger; public function getLogger(): LoggerInterface { return $this->logger; } /** * Inject logger instance (called by the DI container) */ public function setLogger(LoggerInterface $logger): self { $this->logger = $logger; return $this; } }
Then I use this trait in a class:
class UserService { use Logger; /* ... */ }
Because this trait can be used in any class, I create a method injection call for all classes in App
namespace to inject the logger:
App: # ... calls: - [setLogger, ['@monolog.logger']]
However, when Symfony encounters a service that doesn’t implement setLogger
method, it throws an error saying ‘Invalid service: method “setLogger()” does not exist.’
Since this injection is supposed to be optional, is there a way to tell Symfony to ignore the call if the method does not exist?
Advertisement
Answer
You are kinda reinventing the wheel with this one.
Symfony provides this functionality out of the box.
If a service implements LoggerAwareInterface
(link), Symfony will automatically call setLogger()
on the service to inject the logger service.
And since the same package also includes a LoggerAwareTrait
, (link) you can simply do the following:
class FooService implements LoggerAwareInterface { use LoggerAwareTrait; }
And that’s it. If you are using the default autowire/autoconfigure settings, no other configuration needed, and the logger will be automatically injected.
You can implement the above, remove your calls: setLogger
from services.yaml
, and the logger will be injected in the classes you want, are won’t in the classes you don’t.