New in Symfony 7.1: New Dependency Injection Attributes
Symfony includes tens of PHP attributes so you can define metadata next to
your code. In Symfony 7.1 we’ve added some new attributes and in this article
we’ll showcase two of them related to the DependencyInjection component.
AutowireMethodOf Attribute
Contributed by
Nicolas Grekas
in #54016.
Consider a Symfony controller that needs to call a getCommentPaginator() method
from a Doctrine repository called CommentRepository. You could inject the
repository class in the controller action or its constructor. Another alternative
is to use the existing #[AutowireCallable] attribute to do this:
use SymfonyComponentDependencyInjectionAttributeAutowireCallable;
use AppRepositoryCommentRepository;
class SomeController
{
public function showComments(
#[AutowireCallable(service: CommentRepository::class, method: ‚getCommentPaginator‘)]
Closure $getCommentPaginator,
) {
// …
}
}
In Symfony 7.1 we’re introducing a new AutowireMethodOf attribute to simplify
this even more:
use SymfonyComponentDependencyInjectionAttributeAutowireMethodOf;
use AppRepositoryCommentRepository;
class SomeController
{
public function showComments(
#[AutowireMethodOf(service: CommentRepository::class)]
Closure $getCommentPaginator,
) {
// …
}
}
The method name is inferred from the argument name so you don’t need to define it
explicitly as in #[AutowireCallable]. Moreover, if you defined an interface
like this:
interface GetCommentPaginatorInterface
{
public function __invoke(Conference $conference, int $page): Paginator;
}
The previous example could be refactored like this:
#[AutowireMethodOf(CommentRepository::class)]
GetCommentPaginatorInterface $getCommentPaginator,
The benefits of the new #[AutowireMethodOf] attribute are:
Increased flexibility: it allows injecting specific methods as Closures,
providing greater control over what functionality is injected;
Improved readability: thanks to the attribute, the intention behind the
dependency injection is made explicit, improving code clarity;
Enhanced modularity: it decouples services from direct dependencies on
specific class methods, making the codebase more maintainable and testable.
AutowireInline Attribute
Contributed by
Ismail Özgün Turan
and Nicolas Grekas
in #52820.
Service autowiring allows you to manage services in Symfony applications with
minimal configuration. However, sometimes some services need some manual configuration.
In current Symfony applications, you must define that configuration in YAML, XML
or PHP format in a file stored in config/.
In Symfony 7.1 we’re introducing an #[AutowireInline] attribute so you can
define services right inside the related PHP class. Consider the following
service:
class SomeSourceAwareLogger
{
public function __construct(
private readonly LoggerInterface $logger,
private readonly string $someSource,
) {
}
// …
}
To inject this service in another one and configure its constructor arguments,
you no longer have to edit the services configuration file. You can use the
#[AutowireInline] attribute as follows:
use SymfonyComponentDependencyInjectionAttributeAutowireInline;
// …
class SomeClass
{
public function __construct(
#[AutowireInline(class: SomeSourceAwareLogger::class, args: [new Reference(LoggerInterface::class), ‚bar‘])]
public SomeSourceAwareLogger $someSourceAwareLogger,
) {
}
}
If you have defined a factory, use the factory option of the attribute to
define the details:
class SomeClass
{
public function __construct(
#[AutowireInline(
class: SomeSourceAwareLogger::class,
factory: [SomeSourceAwareLoggerFactory::class, ’staticCreate‘],
args: [new Reference(LoggerInterface::class), ’someParam‘],
)]
public SomeSourceAwareLogger $someSourceAwareLogger,
) {
}
}
Using these new attributes is completely optional. If you don’t like them or
they don’t fit your application for any reason, you can keep injecting the dependencies
and defining the services in the configuration file as before.
Symfony Blog