Welcome back! In the previous lesson, we set up the foundation of our MVC ToDo App in Symfony. We created a Todo
entity, set up a TodoService
to manage our todos, and defined a TodoController
to handle requests and render a list of todos using Twig.
Today, we're going to add a critical feature: the ability to add new ToDo items to our list. By the end of this lesson, you will be able to create new tasks and see them displayed in the list.
Let's start by enhancing our TodoService
to allow the creation of new ToDo items. Here is the updated code:
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 public function create($title, $description = null): Todo 28 { 29 // Retrieve current list of todos from the session 30 $todos = $this->findAll(); 31 // Assign a new ID based on the count of existing todos 32 $id = count($todos) + 1; 33 // Create a new Todo object with the provided title and optional description 34 $todo = new Todo($id, $title, $description); 35 // Add new todo to the list 36 $todos[] = $todo; 37 // Save the updated list to the session 38 $this->getSession()->set('todos', $todos); 39 // Return new todo item 40 return $todo; 41 } 42}
In this updated TodoService
, we'll first look at the constructor and the session access. The RequestStack
provides access to the current HTTP request and session, and the getSession
method retrieves the session from the request stack. Moving on to the findAll
method, it fetches all the todos stored in the session, or returns an empty array if none exist.
Now, let's focus on the create
method. This method starts by retrieving the current list of todos. It then assigns a new ID based on the count of existing todos. With the provided title
and optional description
, a new Todo
object is created. Finally, the new todo is added to the list and the session is updated to save this new list.
Next, we'll update our controller to handle the creation of new ToDo items. Here is the updated code for the TodoController
:
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 #[Route('/', name: 'todo_list')] 21 public function list(): Response 22 { 23 $todos = $this->todoService->findAll(); 24 return $this->render('todo/list.html.twig', ['todos' => $todos]); 25 } 26 27 #[Route('/todos/create', name: 'todo_create', methods: ['POST'])] 28 public function create(Request $request): Response 29 { 30 // Retrieve form data from request 31 $title = $request->request->get('title'); 32 $description = $request->request->get('description'); 33 // Call the create method of the TodoService to add a new ToDo item 34 $this->todoService->create($title, $description); 35 // Redirect back to the list view after successfully creating the ToDo item 36 return $this->redirectToRoute('todo_list'); 37 } 38}
In the TodoController
, the constructor initializes the TodoService
instance, allowing the controller to use its methods. The list
method, which you've seen before, fetches all the todos and renders them using the list.html.twig
template.
Let's take a closer look at the create
method. The route annotation maps the URL path /todos/create
to this method and specifies that it only accepts POST requests. The create
method retrieves form data from the POST request, extracts the title
and description
, and calls the create
method of the TodoService
to add the new ToDo item. After successfully creating the ToDo item, the method redirects back to the list view.
Now, let's update our Twig template to include a form that allows users to add new ToDo items. Here is the updated list.html.twig
template:
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>{{ todo.getTitle() }} - {{ todo.getDescription() }}</li> 11 {% else %} 12 <li>No todos found</li> 13 {% endfor %} 14 </ul> 15 <!-- Form to add new ToDo items --> 16 <form action="{{ path('todo_create') }}" method="post"> 17 <input type="text" name="title" placeholder="Title" required> 18 <input type="text" name="description" placeholder="Description"> 19 <!-- Submit button to add the new ToDo item --> 20 <button type="submit">Add To Do</button> 21 </form> 22</body> 23</html>
In this template, the form's action points to the todo_create
route, which we defined in the controller. The form uses the POST method to send data to the server and contains two input fields: one for the title
(required) and one for the description
(optional). A submit button is included to add a new ToDo item when clicked.
Let's walk through an example of adding a new ToDo item.
-
Fill the Form: Enter a
title
and an optionaldescription
in the form fields. -
Submit the Form: Click the
Add To Do
button. -
Form Submission: The form data is sent to the
/todos/create
endpoint as a POST request. -
Controller Handling: The
TodoController
extracts the form data and calls thecreate
method of theTodoService
. -
Service Handling: The
TodoService
creates a newTodo
item and stores it in the session. -
Redirection: The controller redirects back to the list view, where the new ToDo item is now visible.
In this lesson, we expanded our ToDo app by adding the functionality to create new ToDo items. Here is a summary of what we've covered:
-
Updated the TodoService: We added a
create
method to handle the creation of new ToDo items and save them in the session. -
Configured the Controller: We modified the
TodoController
to process form submissions and call the service method to create new ToDo items. -
Modified the Template: We updated the
list.html.twig
template to include a form for adding new ToDo items.
Now it's your turn to practice what you've learned. Head over to the practice exercises and try adding new ToDo items to your list. Remember, practice makes perfect!