This content originally appeared on DEV Community and was authored by jmau111⭐⭐⭐
Injecting dependencies is a fundamental principle that is recommended by various approaches, including SOLID.
More pragmatically, instead of doing this:
namespace App\Services;
class MyService {
private $myDependency;
public function __construct()
{
$this->myDependency = new MyDependency();
}
}
You can do that (PHP 8):
namespace App\Services;
class MyService {
public function __construct(private MyDependency $myDependency)
{}
}
However, you may wonder why it's better and how it works behind the scene.
Injections and autowiring
In a standalone PHP project, you would need to create some class that will have a single but quite essential responsibility: read configs and instantiate objects.
Thanks to this class, you would be able to use the shortcut we saw earlier.
In Symfony, it's usually achieved with built-in interfaces and containers (e.g., ContainerBuilder
, Dependency Injection component), which saves significant time and efforts.
It's not uncommon to read the term "service container." Symfony looks into the config folder to build its containers. That's why you have to write in specific config files.
Symfony does lots of magic behind the scene, providing features likes Autowiring.
By enabling Autowiring, you are telling Symfony to inject dependencies in services automatically:
# config/services.yaml
services:
_defaults:
autowire: true
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Tests,Kernel.php}'
Source: Symfony doc - Autowiring
It prevents manual declarations, and classes are "automatically registered as services and configured to be autowired."
This ways, you can load your dependencies automagically and use them in your controllers.
What's the impact on performances?
Behind the scene, Symfony makes several optimizations we won't see here, including caching and enhanced compilation.
That's why "there is no performance penalty for using autowiring," except on dev environments where the kernel will likely rebuild the container several times.
Ready-to-use containers
Apps powered by Symfony do not have to bother. The containers contains pretty much all services required.
They only have to type-hint them as arguments to start using them.
For example, if you need logs:
namespace App\Service;
use Psr\Log\LoggerInterface;
class MyClass
{
public function __construct(
private LoggerInterface $logger,
) {
}
}
Source: Symfony docs - service config into a service
You can even now specify whether a service should be registered according to the environment thanks to PHP 8 attributes:
#[When(env: 'dev')]
class MyClass
{
}
Wrap up
There's no ultimate approach, but dependency injection is far better for maintenance than manual coupling.
Symfony simplifies the process and runs major optimizations behind the scene, so you practically get this feature for free (in terms of performances) while respecting standards.
This content originally appeared on DEV Community and was authored by jmau111⭐⭐⭐
jmau111⭐⭐⭐ | Sciencx (2023-05-17T11:08:41+00:00) Symfony’s magic: dependency injection. Retrieved from https://www.scien.cx/2023/05/17/symfonys-magic-dependency-injection/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.