Новое в Symfony 4.4: Linter для контейнер сервисов

Symfony включает в себя множество линтеров (проверок), которые являются командами, которые проверяют определенные части приложения (например, lint:yaml для проверки синтаксиса всех файлов YAML конфигураций; lint:twig для проверки синтаксиса всех шаблонов Twig и т. д.)

В Symfony 4 добавили новый линтер, команда для вызова — lint:container. Как вы уже догадались, он проверяет сервисы, определенные в контейнере. В частности, он гарантирует, что аргументы, введенные в сервисы, соответствуют объявлениям типа.

Рассмотрим следующий класс, созданный для службы:

namespace App\SomeNamespace;

class SomeService
{
    public function __construct(int $someProperty = 7)
    {
        // ...
    }
}

Если вы сейчас попытаетесь добавить следующую конфигурацию сервиса:

# config/services.yaml
services:
    App\SomeNamespace\SomeService: ~

При запуске команды lint:container вы увидите следующую ошибку:

Invalid definition for service "App\SomeNamespace\SomeService": argument 1 of
"App\SomeNamespace\SomeService::__construct" accepts "int", "NULL" passed.

Новый контейнерный линтер идет намного дальше и может обнаруживать ошибки, подобные следующим. Рассмотрим этот класс с помощью метода variadic:

namespace App\SomeNamespace;

class SomeService
{
     public function setSomeItems(SomeClass $item, SomeClass ...$items)
    {
        // ...
    }
}

Если вы используете следующее определение сервиса:

# config/services.yaml
services:
    foo:
        class: App\SomeNamespace\SomeClass
    bar:
        class: App\AnotherNamespace\SomeDifferentClass

    App\SomeNamespace\SomeService:
        calls:
            - method: setSomeItems
              arguments:
                  - '@foo'
                  - '@bar'

При запуске команды lint:container вы увидите следующую ошибку:

Invalid definition for service "App\SomeNamespace\SomeService": argument 2 of
"App\SomeNamespace\SomeService::setSomeItems" accepts "App\SomeNamespace\SomeClass",
"App\AnotherNamespace\SomeDifferentClass" passed.

Если вы используете сервис непрерывной интеграции, рассмотрите возможность добавления этой новой команды в список линтеров, выполняемых в каждой сборке. Посмотрите эту ссылку для примера того, как это делается для демонстрационного приложения Symfony.

Проверка типов всех аргументов для всех служб при компиляции контейнера может снизить производительность. Вот почему эта проверка типов реализована на этапе компиляции, называемом CheckTypeDeclarationsPass, который по умолчанию отключен и включен только при выполнении команды lint:container. Если вы не против потери производительности, включите передачу компилятора в вашем приложении.