Créer un CRUD avec Symfony et Doctrine

Dans ce rapide tutoriel, je vais vous montrer comment créer une application Web Symfony 5 CRUD simple et entièrement fonctionnelle.

Sommaire

  • Créer une entité Article
  • Créer le controlleur Article
  • Afficher tous les articles
  • Créer un article
  • Afficher un article
  • Supprimer un article
  • Editer un article

Nous supposons que vous avez installé Symfony 5 sur votre machine

  1. Maintenant, la première chose est de configurer Symfony pour accéder à votre base de données MySQL, allez-y et ouvrez votre parameters.yml situé sous l’application
  2. Configurez le port de votre base de données sur 3306, l’utilisateur de la base de données et le mot de passe de la base de données sur vos valeurs d’installation MySQL, laissez le reste inchangé.
php bin/console doctrine:database:create

Vous devriez voir que la base de données est créée si vous vous connectez à votre console MySQL.

Pour ce tuto, nous allons créer une entité Article de blog.

Allez donc dans votre dossier src/controller et créez un répertoire appelé Entity dans lequel vous placerez un fichier appelé Article.php avec le contenu suivant à l’intérieur des balises php :

<?php

namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="article")
 */
class Article {

    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string", length=100)
     */
    protected $titre;

    /**
     * @ORM\Column(type="string", length=50)
     */
    protected $auteur;

    /**
     * @ORM\Column(type="string", length=1000)
     */
    protected $description;

    /**
     * @return mixed
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * @param mixed $id
     */
    public function setId($id): void
    {
        $this->id = $id;
    }

    /**
     * @return mixed
     */
    public function getTitre()
    {
        return $this->titre;
    }

    /**
     * @param mixed $titre
     */
    public function setTitre($titre): void
    {
        $this->titre = $titre;
    }

    /**
     * @return mixed
     */
    public function getAuteur()
    {
        return $this->auteur;
    }

    /**
     * @param mixed $auteur
     */
    public function setAuteur($auteur): void
    {
        $this->auteur = $auteur;
    }

    /**
     * @return mixed
     */
    public function getDescription()
    {
        return $this->description;
    }

    /**
     * @param mixed $description
     */
    public function setDescription($description): void
    {
        $this->description = $description;
    }
}

Ensuite, allez sur votre terminal et tapez ces commandes pour mettre à jour votre base de données, cette commande va créer les tables et les champs grâce à votre fichier Entity :

php bin/console doctrine:schema:update --force

Créons notre controlleur ensemble. Mettez le contenu suivant sur un fichier php nommé ArticleController.php, à l’intérieur

A) Créer un article ( le C de CRUD )

<?php
// src/Controller/ArticleController.php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use App\Entity\Articles;

class ArticleController extends AbstractController {

    /**
     * @Route("/article/new")
     */
    public function createAction(Request $request) {

        $articles = new Articles();

        $form = $this->createFormBuilder($articles)
            ->add('titre', TextType::class)
            ->add('auteur', TextType::class)
            ->add('description', TextType::class)
            ->add('save', SubmitType::class, ['label' => 'Valider'])
            ->getForm();

        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {

            $articles = $form->getData();

            $em = $this->getDoctrine()->getManager();
            $em->persist($articles);
            $em->flush();

            echo 'Envoyé';
        }

        return $this->render('articles/new.html.twig', [
            'form' => $form->createView(),
        ]);
    }
}

B) Afficher un article ( R de CRUD )

Créons ensemble une vue pour afficher un article spécifique selon son ID

Dans : templates/articles/view.html.twig

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Bootstrap Example</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>

<div class="jumbotron text-center">
    <h1>Mon premier formulaire</h1>
    <p>Un formulaire d'article</p>
</div>

<div class="container">
    <div class="row">

        <table>
            <tbody>
            <tr>
                <th>Titre :</th>
                <td>{{ article.titre }}</td>
            </tr>
            <tr>
                <th>Auteur :</th>
                <td>{{ article.auteur }}</td>
            </tr>
            <tr>
                <th>Description :</th>
                <td>{{ article.description }}</td>
            </tr>

            </tbody>
        </table>
    </div>
</div>

</body>
</html>

Maintenant créons son action dans le controlleur

/**
     * @Route("/article/{id}")
     */
    public function viewAction($id) {
        $article = $this->getDoctrine()->getRepository(Articles::class);
        $article = $article->find($id);

        if (!$article) {
            throw $this->createNotFoundException(
                'Aucun article pour l\'id: ' . $id
            );
        }

        return $this->render(
            'articles/view.html.twig',
            array('article' => $article)
        );

    }

Le code complet :

<?php
// src/Controller/ArticleController.php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use App\Entity\Articles;

class ArticleController extends AbstractController {

    /**
     * @Route("/article/new")
     */
    public function createAction(Request $request) {

        $articles = new Articles();

        $form = $this->createFormBuilder($articles)
            ->add('titre', TextType::class)
            ->add('auteur', TextType::class)
            ->add('description', TextType::class)
            ->add('save', SubmitType::class, ['label' => 'Valider'])
            ->getForm();

        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {

            $articles = $form->getData();
            $em = $this->getDoctrine()->getManager();
            $em->persist($articles);
            $em->flush();

            echo 'Envoyé';
        }

        return $this->render('articles/new.html.twig', [
            'form' => $form->createView(),
        ]);
    }

    /**
     * @Route("/article/{id}")
     */
    public function viewAction($id) {
        $article = $this->getDoctrine()->getRepository(Articles::class);
        $article = $article->find($id);

        if (!$article) {
            throw $this->createNotFoundException(
                'Aucun article pour l\'id: ' . $id
            );
        }

        return $this->render(
            'articles/view.html.twig',
            array('article' => $article)
        );

    }
}

C) Afficher tous les articles de mon entity

Ma vue dans

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Bootstrap Example</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>

<div class="jumbotron text-center">
    <h1>Mon premier formulaire</h1>
    <p>la liste de mes articles</p>
</div>

<div class="container">
    <div class="row">
        {% if articles is not empty %}
            <table>
                <thead>
                <tr>
                    <th>Titre</th>
                    <th>Auteur</th>
                    <th>Description</th>
                    <th>Delete</th>
                    <th>Update</th>
                </tr>
                </thead>
                <tbody>
                {% for article in articles %}
                    <tr>
                        <td>{{ article.titre }}</td>
                        <td>{{ article.auteur }}</td>
                        <td>{{ article.description | slice(0, 20) }}...</td>
                        <td><a href="delete-article/{{ article.id }}">Delete</a></td>
                        <td><a href="update-article/{{ article.id }}">Update</a></td>
                    </tr>
                {% endfor %}
                </tbody>
            </table>
        {% else %}
            <p>No article found.</p>
        {% endif %}
    </div>
</div>

</body>
</html>

J’ajoute dans mon controlleur cette action :

/**
     * @Route("/articles/all")
     */
    public function showAction() {

        $articles = $this->getDoctrine()->getRepository(Articles::class);
        $articles = $articles->findAll();

        return $this->render(
            'articles/list.html.twig',
            array('articles' => $articles)
        );
    }

D) Pour supprimer ( le D de CRUD comme DELETE )

/**
     * @Route("/delete/{id}" , name="article_delete")
     */
    public function deleteAction($id) {

        $em = $this->getDoctrine()->getManager();
        $article = $this->getDoctrine()->getRepository(Articles::class);
        $article = $article->find($id);

        if (!$article) {
            throw $this->createNotFoundException(
                'There are no articles with the following id: ' . $id
            );
        }

        $em->remove($article);
        $em->flush();

        return $this->redirect($this->generateUrl('articles_all'));

    }

E) Editer un article ( U comme UPDATE ( mise à jour ) dans CRUD )

<!DOCTYPE html>
<html lang="fr">
<head>
    <title>Mon premier site</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>

<div class="jumbotron text-center">
    <h1>Mon premier formulaire</h1>
    <p>editer un article</p>
</div>

<div class="container">
    <div class="row">
        {{ form_start(form) }}
        <table>
            <tbody>
            <tr>
                <th>Title:</th>
                <td>{{ form_widget(form.titre) }}</td>
            </tr>
            <tr>
                <th>Author:</th>
                <td>{{ form_widget(form.auteur) }}</td>
            </tr>
            <tr>
                <th>Article Body:</th>
                <td>{{ form_widget(form.description) }}</td>
            </tr>
            <tr>
                <th></th>
                <td>{{ form_widget(form.save) }}</td>
            </tr>
            </tbody>
        </table>

        {{ form_end(form) }}
    </div>
</div>

</body>
</html>

Le controlleur

/**
     * @Route("/edit/{id}", name="article_edit")
     */
    public function updateAction(Request $request, $id) {

        $article = $this->getDoctrine()->getRepository(Articles::class);
        $article = $article->find($id);

        if (!$article) {
            throw $this->createNotFoundException(
                'There are no articles with the following id: ' . $id
            );
        }

        $form = $this->createFormBuilder($article)
            ->add('titre', TextType::class)
            ->add('auteur', TextType::class)
            ->add('description', TextareaType::class)
            ->add('save', SubmitType::class, array('label' => 'Editer'))
            ->getForm();

        $form->handleRequest($request);

        if ($form->isSubmitted()) {
            $em = $this->getDoctrine()->getManager();
            $article = $form->getData();
            $em->flush();

            return $this->redirect($this->generateUrl('articles_all'));

        }

        return $this->render(
            'articles/edit.html.twig',
            array('form' => $form->createView())
        );

    }