Welcome back! In previous lessons, we've covered key Symfony concepts such as creating controllers, defining routes, and utilizing services. In the last lesson, we delved into Services and had a brief introduction to Dependency Injection, both of which are essential for building modular and maintainable Symfony applications.
This time, we will delve deeper into Dependency Injection and explore its extensive use in Symfony. Our primary goal is to build a feature that compares dog breeds utilizing dependency injection. By the end of this lesson, you'll have a better understanding of how to configure services and inject them into a controller.
Let's start with a brief definition. Dependency Injection is a technique where an object (such as a controller) receives the tools it needs (its dependencies) from an external source rather than creating them itself. This promotes loose coupling and makes the code easier to test and maintain.
In Symfony, dependency injection is managed by the service container. The service container keeps track of all the services and their dependencies and automatically injects the required services when needed.
For example, if a controller needs to compare dog breeds using two services, CorgiService
and HuskyService
, instead of creating these services inside the controller, we would inject them via the constructor. This is both cleaner and makes our application more modular.
First, let's create the CorgiService
that our controller will use. This service will provide the breed name of a Corgi dog.
Here is the code for the CorgiService
:
php1<?php 2 3namespace App\Service; 4 5class CorgiService 6{ 7 public function getBreed(): string 8 { 9 return 'Corgi'; 10 } 11}
The CorgiService
class has a method called getBreed
that returns the string 'Corgi'.
Next, let's create the HuskyService
, which will provide the breed name of a Husky dog.
Here is the code for the HuskyService
:
php1<?php 2 3namespace App\Service; 4 5class HuskyService 6{ 7 public function getBreed(): string 8 { 9 return 'Husky'; 10 } 11}
Similarly, the HuskyService
class also has a getBreed
method, which returns the string 'Husky'.
Now let's set up a controller to compare dog breeds. We'll define the DogController
and use dependency injection to access both CorgiService
and HuskyService
.
Here is the code for our controller:
php1<?php 2 3namespace App\Controller; 4 5use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; 6use Symfony\Component\HttpFoundation\Response; 7use App\Service\CorgiService; 8use App\Service\HuskyService; 9 10class DogController extends AbstractController 11{ 12 private $corgiService; 13 private $huskyService; 14 15 public function __construct(CorgiService $corgiService, HuskyService $huskyService) 16 { 17 $this->corgiService = $corgiService; 18 $this->huskyService = $huskyService; 19 } 20 21 public function compareDogs(): Response 22 { 23 $comparison = sprintf( 24 'Comparing breeds: %s vs %s', 25 $this->corgiService->getBreed(), 26 $this->huskyService->getBreed() 27 ); 28 29 return $this->render('comparison.html.twig', ['message' => $comparison]); 30 } 31}
In the DogController
class, we inject CorgiService
and HuskyService
through its constructor, allowing the controller to access these services without creating them internally.
The compareDogs
method uses the getBreed
method from both services to generate a comparison message, which is then rendered using a Twig
template.
This structure ensures that the controller is clean, focusing solely on orchestrating the logic rather than creating dependencies.
In this lesson, we covered the following key concepts:
- The importance and benefits of dependency injection.
- How to create and utilize services in Symfony.
- Setting up a controller in Symfony with dependency injection.
By now, you should have a good understanding of how to use dependency injection to manage dependencies in Symfony, making your application more modular and maintainable. Up next, you'll get hands-on practice through exercises that will reinforce these concepts.
Good luck and happy coding!