Welcome to another step in our journey of adding enterprise features to our Symfony MVC App. In this lesson, we will focus on adapting our existing service class to use the database for managing Todo items instead of sessions, by leveraging Symfony Services and Doctrine ORM.
As a quick reminder from our last lesson, Doctrine ORM helps us manage database operations using PHP objects instead of raw SQL queries. Today, we will update our existing service class to perform CRUD (Create, Read, Update, Delete) operations on our Todo
entity using the database.
Service classes in Symfony encapsulate reusable business logic and help maintain a clean architecture. By the end of this lesson, you will understand how to modify and utilize a TodoService
class that interacts with the database.
Let's start by setting up our TodoService
class for database operations. This service class will manage the CRUD operations for our Todo
entity. We'll need to inject two dependencies into this service: the EntityManagerInterface
and the TodoRepository
.
php1<?php 2 3namespace App\Service; 4 5use App\Entity\Todo; 6use App\Repository\TodoRepository; 7use Doctrine\ORM\EntityManagerInterface; 8 9class TodoService 10{ 11 private $entityManager; 12 private $todoRepository; 13 14 public function __construct(EntityManagerInterface $entityManager, TodoRepository $todoRepository) 15 { 16 $this->entityManager = $entityManager; 17 $this->todoRepository = $todoRepository; 18 } 19}
The EntityManagerInterface
helps manage the entity lifecycle, including persistence operations. Meanwhile, the TodoRepository
provides specific data retrieval methods for the Todo
entity. By injecting these dependencies, our service class now has the necessary tools to interact with the database.
Next, let's implement the CRUD operations in our TodoService
, which will allow us to create, read, update, and delete Todo
items in the database.
We will utilize our previously created TodoRepository
to fetch records from our database. Update the methods in your service class to use the repository for data retrieval.
php1public function findAll(): array 2{ 3 return $this->todoRepository->findAll(); 4} 5 6public function findOne(int $id): ?Todo 7{ 8 return $this->todoRepository->find($id); 9}
For the findAll
and findOne
methods, we use the TodoRepository
:
findAll()
fromTodoRepository
retrieves allTodo
entities from the database.find($id)
fromTodoRepository
finds aTodo
entity by its ID.
The method for creating a new Todo
item in the database remains straightforward. Update your existing method to use the EntityManagerInterface
.
php1public function create(string $title, ?string $description): Todo 2{ 3 $todo = new Todo(); 4 $todo->setTitle($title); 5 $todo->setDescription($description); 6 7 $this->entityManager->persist($todo); 8 $this->entityManager->flush(); 9 10 return $todo; 11}
In the create
method, we:
- Instantiate a new
Todo
object. - Set the title and optional description for the
Todo
item. - Use
persist
to let Doctrine know that we want to save the newTodo
to the database. - Call
flush
to execute the SQL commands that actually insert the newTodo
into the database. Without callingflush
, the changes would not be saved.
To modify an existing Todo
item, update your existing method to use the repository and the EntityManagerInterface
.
php1public function update(int $id, string $title, ?string $description): ?Todo 2{ 3 $todo = $this->findOne($id); 4 if ($todo) { 5 $todo->setTitle($title); 6 $todo->setDescription($description); 7 $this->entityManager->flush(); 8 return $todo; 9 } 10 11 return null; 12}
In the update
method, we:
- Use the
findOne
method to retrieve the existingTodo
by its ID. - If found, update the title and optional description of the
Todo
. - Call
flush
to execute the SQL commands that actually update theTodo
in the database with the new information.
Finally, to remove an existing Todo
item, update your existing method to use the repository and the EntityManagerInterface
.
php1public function delete(int $id): void 2{ 3 $todo = $this->findOne($id); 4 if ($todo) { 5 $this->entityManager->remove($todo); 6 $this->entityManager->flush(); 7 } 8}
In the delete
method, we:
- Use the
findOne
method to retrieve the existingTodo
by its ID. - If found, use
remove
to mark theTodo
for deletion. - Call
flush
to execute the SQL commands that actually remove theTodo
from the database.
Let's put everything together and see the complete, updated TodoService
class.
php1<?php 2 3namespace App\Service; 4 5use App\Entity\Todo; 6use App\Repository\TodoRepository; 7use Doctrine\ORM\EntityManagerInterface; 8 9class TodoService 10{ 11 private $entityManager; 12 private $todoRepository; 13 14 public function __construct(EntityManagerInterface $entityManager, TodoRepository $todoRepository) 15 { 16 $this->entityManager = $entityManager; 17 $this->todoRepository = $todoRepository; 18 } 19 20 public function findAll(): array 21 { 22 return $this->todoRepository->findAll(); 23 } 24 25 public function findOne(int $id): ?Todo 26 { 27 return $this->todoRepository->find($id); 28 } 29 30 public function create(string $title, ?string $description): Todo 31 { 32 $todo = new Todo(); 33 $todo->setTitle($title); 34 $todo->setDescription($description); 35 36 $this->entityManager->persist($todo); 37 $this->entityManager->flush(); 38 39 return $todo; 40 } 41 42 public function update(int $id, string $title, ?string $description): ?Todo 43 { 44 $todo = $this->findOne($id); 45 if ($todo) { 46 $todo->setTitle($title); 47 $todo->setDescription($description); 48 $this->entityManager->flush(); 49 return $todo; 50 } 51 52 return null; 53 } 54 55 public function delete(int $id): void 56 { 57 $todo = $this->findOne($id); 58 if ($todo) { 59 $this->entityManager->remove($todo); 60 $this->entityManager->flush(); 61 } 62 } 63}
In this lesson, we focused on adapting our existing TodoService
class to manage CRUD operations for our Todo
entity using the database:
- Setting up the service class and injecting dependencies.
- Implementing read operations (
findAll
andfindOne
). - Implementing create (
create
), update (update
), and delete (delete
) operations. - Providing a complete code example and explaining each part.
Now that you have a solid understanding of implementing a service class with CRUD operations using Doctrine
, it's time to put your knowledge into practice. Proceed to the practice exercises and apply what you've learned. These hands-on tasks will reinforce your understanding and help you become proficient in managing database operations within your Symfony application.
Great job on getting through this lesson! Keep up the excellent work as you continue to build and enhance your Symfony MVC app.