Symfony includes plenty of linters, which are commands that validate certain
parts of the application (e.g. lint:yaml
to check the syntax of all YAML
config files; lint:twig
to check the syntax of all Twig templates, etc.)
In Symfony 4 we added a new linter called lint:container
. As you may have
guessed, it checks the services defined in the container. Specifically, it
ensures that arguments injected into services match type declarations.
Consider the following class created for a service:
1 2 3 4 5 6 7 8 9
namespace App\SomeNamespace;
class SomeService
{
public function __construct(int $someProperty = 7)
{
// ...
}
}
If you now try to add the following service configuration:
1 2 3
# config/services.yaml
services:
App\SomeNamespace\SomeService: ~
You'll see the following error when running the lint:container
command:
1 2
Invalid definition for service "App\SomeNamespace\SomeService": argument 1 of
"App\SomeNamespace\SomeService::__construct" accepts "int", "NULL" passed.
The new container linter goes much further and it can detect errors like the following. Consider this class with a variadic method:
1 2 3 4 5 6 7 8 9
namespace App\SomeNamespace;
class SomeService
{
public function setSomeItems(SomeClass $item, SomeClass ...$items)
{
// ...
}
}
If you use the following service definition:
1 2 3 4 5 6 7 8 9 10 11 12 13
# config/services.yaml
services:
foo:
class: App\SomeNamespace\SomeClass
bar:
class: App\AnotherNamespace\SomeDifferentClass
App\SomeNamespace\SomeService:
calls:
- method: setSomeItems
arguments:
- '@foo'
- '@bar'
You'll see the following error when running the lint:container
command:
1 2 3
Invalid definition for service "App\SomeNamespace\SomeService": argument 2 of
"App\SomeNamespace\SomeService::setSomeItems" accepts "App\SomeNamespace\SomeClass",
"App\AnotherNamespace\SomeDifferentClass" passed.
If you are using a continuous integration service, consider adding this new command to the list of linters executed on each build. Check out this link for an example of how we do that for the Symfony Demo application.
Checking the types of all arguments for all services whenever the container is
compiled can hurt performance. That's why this type checking is implemented in
a compiler pass called CheckTypeDeclarationsPass
which is disabled by
default and enabled only when executing the lint:container
command. If you
don't mind the performance loss, enable the compiler pass in your application.
Awesome!
Amazing !
Awesome!
So nice! Thank you so much.