Download the PHP package kostislav/php-class-symfony-service-config without Composer
On this page you can find all versions of the php package kostislav/php-class-symfony-service-config. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download kostislav/php-class-symfony-service-config
More information about kostislav/php-class-symfony-service-config
Files in kostislav/php-class-symfony-service-config
Package php-class-symfony-service-config
Short Description Class-based service configuration for Symfony
License MIT
Informations about the package php-class-symfony-service-config
PHP-based Symfony service configuration
The Symfony framework offers three methods of configuring its Dependency Injection Container: XML configuration, YAML configuration and PHP configuration. The XML and YAML approaches are a little developer-unfriendly because of things like missing IDE completion. The PHP approach tries to solve these problems, but instead of using PHP directly, it invents a DSL on top of PHP and in turn suffers from the same problems, albeit to a lesser degree.
This library offers a different method of configuring services using plain PHP, heavily inspired by Java's Spring framework Java-based configuration.
NOTE: The library makes extensive use of PHP attributes, which means it requires at least PHP 8.0.
Example
Consider the following simple setup: One public service depending on two other services. In Symfony PHP config, it might look like this:
Or, if you prefer YAML:
Using this library, you can write the same definition like this:
For this simple example, the code might not be shorter, but there is an obvious advantage: the creation of your services is written in plain PHP. IDE features like code completion, type hinting and usage analysis work out of the box. And if you need to do something more complicated, like calling a setter or using a static factory method, you can do it like in any other place in your codebase - no need to learn yet another expression language to call a method on another service.
Setting it up
- Add a composer dependency on
kostislav/php-class-symfony-service-config
-
Unfortunately, Symfony does not offer any way for the library to hook into the right internals, so a manual change of your
Kernel
class is necessary. Add the following line to theconfigureContainer
method: - Register your configuration classes with the
$loader
. A convenient place to do it is in theKernel
class, just below the line added in step 2.
What it does
By default, each public non-static method in the config class that is annotated with the ServiceDefinition
attribute will be used to create a private service with the same name as that method. This method must have a return type hint. Any parameters of this method will be added as dependencies of this service and will be resolved by name.
The config class itself must have a no-argument constructor.
Explicitly naming a service
If you need a service to have a name other than the defining method, pass it to the ServiceDefinition
attribute.
Public services
In Symfony, services are by default private and cannot be requested from the container. Things like controllers need to be marked as public. This is controlled by the isPublic
parameter of the ServiceDefinition
attribute.
Using a service with a name that cannot be used as a PHP identifier
Symfony is full of services with names like annotations.cached_reader
. As PHP won't allow us to use parameter names like that, you can specify the name of the injected service explicitly using the Service
parameter attribute.
Using container parameters
Method parameters annotated with the Parameter
attribute will be populated with the corresponding container parameter rather than a service. Again, by default, the method parameter name is used as the name of the parameter to look up, but another name can be specified on the attribute.
Splitting the configuration class
When you have a lot of services, the configuration class can get long. You can split it into multiple classes and either load each of them in your Kernel
, or just load one of them and use the Import
attribute to include the other ones. Services from the imported classes will be available in the importing config class.
Imports work transitively - if the imported class itself has another Import
attribute with another class, that class will be included as well.
Service tags
If you need to tag your service, just add a Tag
attribute. There can be multiple Tag
attributes on the same method.
Performance
What is the performance impact of all this reflection and attribute reading?
Don't worry, the configuration classes are only analyzed once when the container is built, at the same time the services.yaml
file would get parsed. After that, the performance difference compared to the other approaches is one additional method call (of the service definition method), which isn't noticeable at all.