Welcome back! In previous lessons, you've already learned how to list, create, and update ToDo items in our Symfony-based MVC application. Now, we will add one final and essential piece of functionality: the ability to delete ToDo items from the list.
Deleting items is an essential feature for any ToDo app because it allows users to manage their tasks more effectively. Imagine having a long list of completed or irrelevant tasks — you want an easy way to remove those items, right? By the end of this lesson, you'll be able to delete any ToDo item from your list.
First, let's add the necessary logic to our service layer. The service layer is responsible for handling your application's business logic. In this case, it will manage the deletion of ToDo items.
We'll be working with the TodoService.php
file. Here's the code you need to add to your TodoService
class:
php1<?php 2 3namespace App\Service; 4 5use App\Entity\Todo; 6use Symfony\Component\HttpFoundation\RequestStack; 7 8class TodoService 9{ 10 private $requestStack; 11 12 public function __construct(RequestStack $requestStack) 13 { 14 $this->requestStack = $requestStack; 15 } 16 17 private function getSession() 18 { 19 return $this->requestStack->getSession(); 20 } 21 22 public function findAll(): array 23 { 24 return $this->getSession()->get('todos', []); 25 } 26 27 // Existing methods... 28 29 public function delete($id): void 30 { 31 $todos = $this->findAll(); 32 // Iterating through the list of ToDo items 33 foreach ($todos as $key => $todo) { 34 if ($todo->getId() == $id) { 35 // Remove the ToDo item from the array 36 unset($todos[$key]); 37 // Re-index the array and save it back to the session 38 $this->getSession()->set('todos', array_values($todos)); 39 break; 40 } 41 } 42 } 43}
In this code, the first step is to retrieve the current list of ToDo items from the session using the findAll
method. We then iterate through the list to find the ToDo item with the matching ID. Once found, we use the unset
function to remove the item from the array. Finally, we re-index the array (to avoid gaps in the index) and save the updated list back to the session. By adding this method, you've now defined how a ToDo item will be deleted from your session.
Next, we need to create an endpoint in our controller to handle the deletion request. Let's update the TodoController.php
file to include a route and method for deleting ToDo items.
php1<?php 2 3namespace App\Controller; 4 5use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; 6use Symfony\Component\HttpFoundation\Response; 7use Symfony\Component\HttpFoundation\Request; 8use Symfony\Component\Routing\Annotation\Route; 9use App\Service\TodoService; 10 11class TodoController extends AbstractController 12{ 13 private $todoService; 14 15 public function __construct(TodoService $todoService) 16 { 17 $this->todoService = $todoService; 18 } 19 20 // Existing methods... 21 22 #[Route('/todos/{id}/delete', name: 'todo_delete', methods: ['POST'])] 23 public function delete($id): Response 24 { 25 $this->todoService->delete($id); 26 return $this->redirectToRoute('todo_list'); 27 } 28}
Here, we define a new route for deleting ToDo items. This route uses the POST method and requires an ID parameter. The delete
method in the controller calls the delete
method from the TodoService
class to remove the specified ToDo item. After the ToDo item is deleted, the user is redirected back to the main list view using the redirectToRoute('todo_list')
method. By setting up this route and method, you ensure that your app can properly handle delete requests.
The final step is to update our list.html.twig
template to include a "Delete" button for each ToDo item. Twig templates in Symfony are used to render the views of your application.
HTML, XML1<!DOCTYPE html> 2<html> 3<head> 4 <title>ToDo List</title> 5</head> 6<body> 7 <h1>ToDo List</h1> 8 <ul> 9 {% for todo in todos %} 10 <li> 11 <a href="{{ path('todo_detail', {'id': todo.id}) }}"> 12 {{ todo.getTitle() }} - {{ todo.getDescription() }} 13 </a> 14 <!-- Form for deleting a ToDo item --> 15 <form action="{{ path('todo_delete', {'id': todo.id}) }}" method="post" style="display: inline;"> 16 <button type="submit">Delete</button> 17 </form> 18 </li> 19 {% else %} 20 <li>No todos found</li> 21 {% endfor %} 22 </ul> 23 24 <form action="{{ path('todo_create') }}" method="post"> 25 <input type="text" name="title" placeholder="Title" required> 26 <input type="text" name="description" placeholder="Description"> 27 <button type="submit">Add To Do</button> 28 </form> 29</body> 30</html>
In this template, for each ToDo item in the list, a form with a Delete
button is created. The form's action
attribute is set to the delete route using path('todo_delete', {'id': todo.id})
. When the Delete
button is clicked, the form sends a POST request to the delete endpoint, and the specified ToDo item is deleted. By updating your template, users can now visually interact with the delete functionality.
Let's go through a complete example of deleting a ToDo item.
- Click Delete button: Click the "Delete" button next to the desired ToDo item on the list page.
- Form submission: The form sends a POST request to the delete endpoint.
- Controller processes delete:
delete
method inTodoController
processes the request. - Service deletes item:
TodoService
removes the ToDo item from the session. - View updated list: You are redirected back to the list view, now without the deleted item.
Congratulations! You've successfully added the ability to delete ToDo items in your Symfony-based MVC application. Here's a quick recap of what we've covered:
- We added a
delete
method to theTodoService
to handle the deletion logic. - We created a new route and method in the
TodoController
to handle delete requests. - We updated the
list.html.twig
template to include aDelete
button for each ToDo item.
By completing this lesson, you've built out all the core functionalities of a ToDo app: listing, creating, updating, and deleting items. Now it's time to go to the practice exercises and test your skills further. Keep coding!