loophp/service-alias-autoregister-bundle

Auto register services aliases in the Symfony container.

Fund package maintenance!
drupol

Installs: 3

Dependents: 0

Suggesters: 0

Security: 0

Stars: 1

Watchers: 1

Forks: 0

Open Issues: 4

Type:symfony-bundle

1.0.0 2022-02-04 16:20 UTC

This package is auto-updated.

Last update: 2022-11-30 02:16:08 UTC


README

Latest Stable Version GitHub stars Total Downloads License Donate!

Service Alias Auto Register

A bundle for Symfony.

Description

The S.O.L.I.D. principles are a set of five design principles intended to make software designs more understandable, flexible, and maintainable.

One of these principles is the Open-Closed Principle, which promotes the use of interfaces instead of concrete implementations.

In Symfony, when injecting services, we usually rely on concrete service implementations rather than using an interface. This makes our code less flexible and sometimes harder to test.

This issue can be fixed in Symfony by adding aliases in the container. Sadly, you have to do it manually and for each class.

Then, in order to fix this issue and improve this behavior, this bundle will declare new aliases in the Symfony container.

Aliases are automatically created when the discovered services implements interfaces.

If a service implements 3 interfaces, 3 new aliases are created in the container.

Aliases are automatically created using the service's class FQDN, when the discovered services implements one or many interfaces.

Aliases let you inject services using interfaces and named parameters instead of specific implementations and thus, fix the Open-Closed Principle that we usually do not follow.

The following examples are showing an existing situation, as you can see, we do not respect that principle and we inject an concrete implementation directly:

<?php

declare(strict_types=1);

namespace App\Controller;

use App\Repository\UserRepository;

final class MyTestController
{
    // Here we inject a concrete implementation of a Doctrine repository.
    public function __invoke(UserRepository $userRepository): Response
    {
        // Do stuff.
    }
}

When the bundle is enabled, you can inject the repository using an interface, using a specific parameter name.

<?php

declare(strict_types=1);

namespace App\Controller;

use Doctrine\Persistence\ObjectRepository;

final class MyTestController
{
    // Here we inject the UserRepository (which implements ObjectRepository)
    // using the variable which has been created from the UserRepository class name.
    public function __invoke(ObjectRepository $userRepository): Response
    {
        // Do stuff.
    }
}

We can even do better by injecting it in the constructor. Then we can use the interface when injecting, and we can use the implementation in the property. Best of both world.

<?php

declare(strict_types=1);

namespace App\Controller;

use App\Repository\UserRepository;
use Doctrine\Persistence\ObjectRepository;

final class MyTestController
{
    private UserRepository $userRepository;

    public function __construct(ObjectRepository $userRepository)
    {
        $this->userRepository = $userRepository;
    }

    public function __invoke(): Response
    {
        // Do stuff.
    }
}

Installation

composer require loophp/service-alias-autoregister-bundle

See the next section to learn how to enable it in your project.

Usage

The bundle can be enabled by just adding a specific tag: autoregister.alias

Adds all the aliases it can find

services:
    App\:
        resource: '../src/*'
        exclude: '../src/{DependencyInjection,Entity,Tests,Kernel.php}'
        tags:
            - { name: autoregister.alias }

Adds only specific services implementing specific interfaces only

services:
    _instanceof:
        Doctrine\Persistence\ObjectRepository:
            tags:
                - { name: autoregister.alias }

Once it is done, do the following command to verify:

bin/console debug:container --tag=autoregister.alias

Another example: find all the new aliases for Doctrine repositories:

bin/console debug:container ObjectRepository

Configure the bundle

You can configure this bundle by creating a configuration file in your application.

service_alias_auto_register:
    whitelist: ~
    blacklist:
        - Countable
        - Psr\Log\LoggerAwareInterface
        - Symfony\Contracts\Service\ServiceSubscriberInterface

The configuration keys that are available:

  • whitelist: Let you configure a list of interface to use. Empty the list to whitelist them all.
  • blacklist: Let you configure a list of interface to ignore. Default is empty array. It takes precedence on the whitelist.

Contributing

Feel free to contribute by sending Github pull requests.

If you can't contribute to the code, you can also sponsor me on Github.

Changelog

See CHANGELOG.md for a changelog based on git commits.

For more detailed changelogs, please check the release changelogs.