Lesson 2
Implementing Database Services in Symfony
Implementing Database Services in Symfony

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.

Setting Up the TodoService

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.

php
1<?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.

Read Operations

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.

php
1public 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() from TodoRepository retrieves all Todo entities from the database.
  • find($id) from TodoRepository finds a Todo entity by its ID.
Create Operation

The method for creating a new Todo item in the database remains straightforward. Update your existing method to use the EntityManagerInterface.

php
1public 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 new Todo to the database.
  • Call flush to execute the SQL commands that actually insert the new Todo into the database. Without calling flush, the changes would not be saved.
Update Operation

To modify an existing Todo item, update your existing method to use the repository and the EntityManagerInterface.

php
1public 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 existing Todo by its ID.
  • If found, update the title and optional description of the Todo.
  • Call flush to execute the SQL commands that actually update the Todo in the database with the new information.
Delete Operation

Finally, to remove an existing Todo item, update your existing method to use the repository and the EntityManagerInterface.

php
1public 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 existing Todo by its ID.
  • If found, use remove to mark the Todo for deletion.
  • Call flush to execute the SQL commands that actually remove the Todo from the database.
Complete Service

Let's put everything together and see the complete, updated TodoService class.

php
1<?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}
Summary and Next Steps

In this lesson, we focused on adapting our existing TodoService class to manage CRUD operations for our Todo entity using the database:

  1. Setting up the service class and injecting dependencies.
  2. Implementing read operations (findAll and findOne).
  3. Implementing create (create), update (update), and delete (delete) operations.
  4. 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.

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.