Reputation:
I have some events in my project that uses DI. When my events are an instance of App\Manager\ValidatorAwareInterface I configure then to inject the @validator service.
When I have this code in the services.yaml it works :
services:
_instanceof:
App\Manager\Validator\ValidatorAwareInterface:
calls:
- method: setValidator
arguments:
- '@validator'
But when I put this same code in a manager.yaml file that I import in the services.yaml, it does not work anymore :
imports:
- { resource: manager.yaml }
Do you have an idea why ?
Thanks.
Upvotes: 0
Views: 1083
Reputation: 48865
@stephan.mada's answer will probably fix your problem.
But I would like to point out a little known annotation called '@required' which eliminates the need to explicitly configure your setter at all.
use Symfony\Component\Validator\Validator\ValidatorInterface;
trait ValidatorTrait
{
/** @var ValidatorInterface */
protected $validator;
/** @required */
public function injectValidator(ValidatorInterface $validator)
{
$this->validator = $this->validator ?: $validator;
}
}
The '@required' before the inject method causes the container to automatically inject the dependency. Your setter stuff in services.yaml can go away completely. You don't see a whole lot of usage of '@required' but it does come in handy for commonly injected services.
You might also notice that I used a trait here. With a trait, I no longer need a base class or interface. Any service that uses the trait will automatically get the validator service injected. You can of course just use a conventional class if you like.
class SomeService
{
use ValidatorTrait; // And the validator is now available
use RouterTrait; // As well as the router
And one final note. I added a guard to ensure that the validator can only be injected once. This protects against rogue programmers who might be tempted to inject a different validator at some other point in the cycle.
Upvotes: 6
Reputation: 1130
I think you should copy symfony's default service configuration in your manager.yaml before defining others services since the default configuration is only applied to the services defined in that file. The new Default services.yaml File
# config/manager.yaml
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
public: false # Allows optimizing the container by removing unused services; this also means
# fetching services directly from the container via $container->get() won't work.
# The best practice is to be explicit about your dependencies anyway.
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/*'
exclude: '../src/{Entity,Migrations,Tests}'
# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
App\Controller\:
resource: '../src/Controller'
tags: ['controller.service_arguments']
# add more service definitions when explicit configuration is needed
# please note that last definitions always *replace* previous ones
Upvotes: 2