Symfony

PROJET IMMO'Bill

MVC, CRUD etc.. découvrez un projet exceptionnel!

Introduction

Nous explorerons le fonctionnement du site Immo'Bill en passant en revue ses diverses fonctionnalités.

Le site se compose de diverses sections, incluant les biens, les propriétaires, les types de biens, les contacts et autres éléments clés.

Mon rôle principal concerne les propriétaires et le développement d’un formulaire de connexion. Nous aborderons chaque caractéristique en détaillant la navigation sur le site, la gestion des propriétés, les interactions avec les propriétaires, l’exploration des différentes catégories de biens, et plus encore.

Pour conclure, nous dresserons un bilan des leçons apprises au cours de ce projet, en soulignant les points forts, les défis rencontrés et les solutions adoptées. Cette analyse nous aidera à comprendre nos apprentissages et à identifier des opportunités d’amélioration pour l’avenir.

Contexte

L’agence immobilière Immo’Bill, basée à Pau, envisage de développer un site web pour exposer ses biens immobiliers à la vente. Ce site offrira aux visiteurs la possibilité de parcourir les propriétés disponibles et d’obtenir des détails sur chacune d’elles. En parallèle, il est prévu un espace dédié à l’équipe pour l’ajout de nouveaux biens, la gestion des membres, des propriétaires, et des différentes catégories de propriétés.

Pour satisfaire ces exigences, il est essentiel d’intégrer un formulaire de connexion. Ce formulaire permettra aux utilisateurs de se connecter en tant qu’administrateur ou membre standard, garantissant ainsi la sécurité et une gestion efficace du site.

Immo bill logo

Diagramme de classe de l'application

Partie 1

Formulaire de connexion

Création de Admin et un utilisateur

Il est important de s’assurer que l’administrateur accède à ses droits spécifiques uniquement après s’être connecté. Pour garantir cette sécurité, nous installerons un formulaire de connexion exclusivement réservé aux administrateurs. Ce processus leur permettra d’accéder aux fonctionnalités exclusives après une authentification réussie. Nous aborderons aussi la création d’adresses e-mail, la génération de mots de passe sécurisés, et le développement d’un formulaire de connexion approprié.

Avant de développer le formulaire de connexion, j’ai commencé par mettre en place une entité « User » en utilisant la commande appropriée

Symfony console make:user

Après avoir répondu aux questions de la console, comme le nom de l’entité, l’utilisation de Doctrine, et la sécurisation du mot de passe, et suite à la mise à jour de la table dans la base de données, j’ai procédé à l’ajout de deux utilisateurs : un administrateur doté du rôle « Rôle_Admin » et un utilisateur standard.

Le mot de passe a une apparence inhabituelle car il est haché. En effet, cela évite d’afficher
le mot de passe en clair, ce qui renforce la sécurité. Pour créer un mot de passe haché, j’ai
utilisé la commande

composer require symfony/password-hasher

Création du formulaire de connexion

Pour créer un formulaire de connexion, nous utiliserons une commande spécifique qui génère automatiquement les fichiers et contrôleurs nécessaires.

Symfony console make:auth

Une fois avoir répondu aux options nécessaires

Des fichiers sont créés, on les modifiera par la suite. Ces fichiers devront être modifiés pour améliorer leur rendu visuel et rediriger les utilisateurs
connectés vers les bons endroits. De plus, nous pouvons afficher les outils nécessaires aux
utilisateurs, tels que les outils de gestion pour l’administrateur.

				
					symfony console make:auth

What style of authentication do you want? [Empty authenticator]:
 [0] Empty authenticator
 [1] Login form authenticator
> 1

The class name of the authenticator to create (e.g. AppCustomAuthenticator):
> LoginFormAuthenticator

Choose a name for the controller class (e.g. SecurityController) [SecurityController]:
> SecurityController

Do you want to generate a '/logout' URL? (yes/no) [yes]:
> yes

 created: src/Security/LoginFormAuthenticator.php
 updated: config/packages/security.yaml
 created: src/Controller/SecurityController.php
 created: templates/security/login.html.twig
				
			

Le code suivant affiche les informations de connexion provenant de l'entité user
{{ app.user.userIdentifier }}.

				
					{% if app.user %}
  <div class="mb-3">
    Connecté en tant que
    {{ app.user.userIdentifier }}
    -
    <a href="{{ path('app_logout') }}">Déconnexion</a>
  </div>
{% endif %}

<div class="formulaire-logo-text">
  <h1 class="h3 mb-3 font-weight-normal">Hey! Veuillez vous connecter.</h1>
  <img decoding="async" src="{{ asset('images/immobill.png') }}" id="logo-immobill" style="width:55px;height:55px;" />
</div>

<div class="bloc-cred">
  <label for="inputEmail">Email</label>
  <input type="email" value="{{ last_username }}" name="email" id="inputEmail" class="form-control" autocomplete="email" required autofocus />
</div>
<div class="bloc-cred">
  <label for="inputPassword">Mot de passe</label>
  <input type="password" name="password" id="inputPassword" class="form-control" autocomplete="current-password" required />
</div>

<input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}" />

<div class="checkbox mb-3" >
  <label><input style="margin-right: 5px;" type="checkbox" id="se-souvenir-de-moi" name="_remember_me" />Se souvenir de moi</label>
</div>

<button class="btn btn-lg btn-primary" type="submit">Se connecter</button>

				
			

On peut voir ici que la sécurité CSRF a été appliqué.

				
					<input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}" />
				
			

Lorsque l’admin est connecté, il est redirigé vers l'Accueil via la route appartenant à la fonction onAuthenticationSuccess()

				
					public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
    if ($targetPath = $this->getTargetPath($request->getSession(), $firewallName)) {
        return new RedirectResponse($targetPath);
    }

    return new RedirectResponse($this->urlGenerator->generate('accueil'));
    // throw new \Exception('TODO: provide a valid redirect inside '.__FILE__);
}

protected function getLoginUrl(Request $request): string
{
    return $this->urlGenerator->generate(self::LOGIN_ROUTE);
}

				
			

Qui dirige vers l'accueil

Attribution des droits

Maintenant que l’administrateur est configuré et que le formulaire de connexion est sécurisé, nous pouvons aborder la manière d’afficher des fonctionnalités spécifiques en fonction de ses rôles. Cela inclut la gestion des biens, des membres, et des propriétaires. Dans l’interface du menu, les utilisateurs standards verront des options limitées. Une condition spécifique est intégrée pour que seule une personne avec le rôle d’administrateur puisse accéder à la gestion des membres.

				
					{% if app.user %}
					<li class="nav-item dropdown">
						<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">Gestion</a>
						<ul class="dropdown-menu">
							<li>
								<a class="dropdown-item" href="{{ path('lesBiensAdmin') }}">Biens</a>
							</li>
							<li>
								<a class="dropdown-item" href="{{ path('lesProprietairesAdmin') }}">Propriétaires</a>
							</li>
							<li>
								<a class="dropdown-item" href="{{ path('lesTypesAdmin') }}">Types</a>
							</li>
							{% if is_granted('ROLE_ADMIN') %}
								<li>
									<a class="dropdown-item" href="{{ path('lesMembresAdmin') }}">Membres</a>
								</li>
							{% endif %}
						</ul>
					</li>
				{% endif %}
				
			

En conclusion, le formulaire de connexion a été mis en place avec succès, garantissant l’attribution des droits appropriés aux différents utilisateurs. Un administrateur bénéficie de droits exclusifs après s’être connecté via un formulaire spécialement conçu à cet effet. Le processus a inclus l’établissement d’une entité utilisateur avec des rôles définis, la sécurisation des mots de passe par hachage, la mise en place du formulaire de connexion avec Symfony, et l’adaptation de l’affichage selon les rôles de chaque utilisateur.

La sécurité CSRF a également été intégrée pour protéger le formulaire contre les attaques de falsification de requêtes intersites. Des fonctionnalités spéciales, comme la gestion des membres, sont exclusivement accessibles aux administrateurs, grâce à une gestion conditionnelle des droits dans l’interface du menu.

Partie 2

Gestion Propriétaire

Contrôleurs

contrôleurs arborescence

Data Fixtures

data fixtures arborescence

Entités

entités arborescence

Form (formulaire)

Forms arborescence

Repository

repository arborescence

Templates

Templates arborescence

Consulter

Avant de pouvoir interagir avec les informations des propriétaires, il est nécessaire de les consulter. Depuis le menu, l'administrateur dispose de plusieurs options, telles que choisir parmi les biens, les propriétaires, les types de biens, et les membres. Dans notre cas, l'administrateur commencera simplement par cliquer sur l'option "Propriétaire".

Jetons un coup d’œil à quoi correspond notre lien pour « Propriétaire » dans notre code

				
												<li>
								<a class="dropdown-item" href="{{ path('lesProprietairesAdmin') }}">Propriétaires</a>
							</li>
				
			
				
					class AdminProprioController extends AbstractController
{
    #[Route('/admin/proprietaires', name: 'lesProprietairesAdmin')]
    public function index(ProprietairesRepository $lesProprio): Response
    {
        $lesProprio = $lesProprio->findAll();
        return $this->render('admin/admin_proprio/adminProprio.html.twig', [
            'lesProprio' => $lesProprio,
        ]);
    }
}

				
			

Le lien "Propriétaire" redirige vers "lesProprietairesAdmin". En travaillant avec Symfony, cela indique qu'il s'agit d'un nom de route qui correspond à une fonction spécifique lorsque l’admin clique dessus.
Analysons la fonction en question :

La route admin/propriétaires est ce qui s’affichera dans notre barre d’URL. La fonction
Index() a pour paramètre $lesProprio de la classe ProprietairesRepository. Cette classe
possède la méthode findAll(), qui récupère toutes les données liées à la classe Proprietaire,
agissant ainsi sur les données des propriétaires. La variable $lesProprio contient les
données récupérées.

				
					return $this->render('admin/admin_proprio/adminProprio.html.twig', [
            'lesProprio' => $lesProprio,
        ]);
				
			

AdminProprioController()

				
					public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, Proprietaires::class);
    }
				
			
				
					return $this->render('admin/admin_proprio/adminProprio.html.twig', [
            'lesProprio' => $lesProprio,
        ]);
				
			

ProprietairesRepository

				
					class Proprietaires
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\Column(length: 255)]
    private ?string $nom = null;
				
			

Proprietaires

Affichage des données

				
					class AdminProprioController extends AbstractController
{
    #[Route('/admin/proprietaires', name: 'lesProprietairesAdmin')]
    public function index(ProprietairesRepository $lesProprio): Response
    {
        $lesProprio = $lesProprio->findAll();
        return $this->render('admin/admin_proprio/adminProprio.html.twig', [
            'lesProprio' => $lesProprio,
        ]);
    }
}

				
			

Le lien "Propriétaire" redirige vers "lesProprietairesAdmin". En utilisant Symfony, cela signifie que le lien fait référence à un nom de route associé à une fonction spécifique activée lorsque l'administrateur clique dessus. Analysons donc en détail cette fonction :

Une fois les données récupérées, la fonction redirige l’utilisateur vers une interface dont le
chemin est spécifié dans le rendu (render). Dans ce cas, l’utilisateur sera dirigé vers
« adminProprio.html.twig », qui représente la vue globale des propriétaires. Il est important
d’afficher les données récupérées, qui sont stockées dans la variable $lesProprio, dans
cette vue.

Explication récupération données

Rendu de l’interface

interface liste des proprios

En résumé, après avoir sélectionné l’option « Propriétaire » dans le menu, nous avons été redirigés vers « lesProprietairesAdmin ». Au sein de cette fonction, nous avons récupéré les données relatives aux propriétaires, les avons stockées dans une variable, puis les avons présentées dans la vue. Désormais, plusieurs actions sont à notre disposition, notamment Ajouter, Modifier et Supprimer.

Ajouter

Dans la vue `adminProprio.html.twig`, que j'ai mentionnée précédemment, nous avons non seulement la capacité d'afficher des données, mais également d'ajouter, de modifier ou de supprimer des propriétaires. En effet, cette vue inclut des boutons qui facilitent la navigation vers ces fonctions spécifiques. Par exemple, le bouton associé à l'option "Propriétaire" dans le menu dirige vers la fonction que nous avons explorée. Voici comment ce bouton permet de rediriger vers cette fonction spécifique.
				
					<a class="btn btn-primary bouton-ajout button" href="{{ path('admin_proprio_ajout') }}">Ajouter</a>

				
			
				
					    #[Route('/admin/proprietaire/ajout', name: 'admin_proprio_ajout')]
    #[Route('/admin/proprietaire/modifier/{id}', name: 'admin_proprio_modification')]
    //, methods: ['GET', 'POST']
    public function ajoutEtModif(Proprietaires $lesProprio = null, Request $request, EntityManagerInterface $manager): Response
    {
        if (!$lesProprio) {
            $lesProprio = new Proprietaires();
        }
        $form = $this->createForm(ProprioType::class, $lesProprio);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $manager->persist($lesProprio);
            $manager->flush();
            $this->addFlash('success', 'Action effectué avec succès!');
            return $this->redirectToRoute("lesProprietairesAdmin");
        }

        return $this->render('admin/admin_proprio/modificationProprio.html.twig', [
            'proprio' => $lesProprio,
            'form' => $form->createView(),
            "isModification" => $lesProprio->getId() !== null
        ]);
    }
				
			

La redirection se fait vers `admin_proprio_ajout`, qui exploite la fonction `ajoutEtModif()`. Cette fonction est versatile, car elle permet à la fois d’ajouter et de modifier des éléments :

1. Ajout : Si aucun objet « Proprietaires » n’est fourni, cela indique qu’il s’agit d’une opération d’ajout. Dans ce cas, un nouvel objet « Proprietaires » est créé pour permettre l’insertion de nouvelles données.

2. Modification : Si un objet « Proprietaires » est déjà fourni, cela signifie qu’il s’agit d’une modification. La fonction utilise alors cet objet existant pour remplir préalablement le formulaire de modification avec les données existantes.

Dans le contexte actuel, nous nous orientons principalement vers la première option, c’est-à-dire l’ajout d’un nouveau propriétaire. Nous serons donc redirigés vers notre formulaire qui, initialement, sera vide. Il est important de noter que dans notre structure de fichiers, le formulaire destiné aux propriétaires est nommé `ProprioType`.

Dans ce cas, la variable `$form` sera instanciée à l’intérieur de la classe `ProprioType`. Elle intégrera les champs spécifiés dans cette classe, tels que le nom, le prénom, l’e-mail, le téléphone et l’adresse. Ces champs seront utilisés pour collecter les informations nécessaires lors de la création ou de la modification d’un propriétaire dans le système.

				
					$form = $this->createForm(ProprioType::class, $lesProprio);
$form->handleRequest($request);
				
			
				
					class ProprioType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('nom', TextType::class)
            ->add('prenom', TextType::class)
            ->add('mail', TextType::class)
            ->add('tel', TextType::class)
            ->add('adresse', TextType::class);
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class' => Proprietaires::class,
        ]);
    }
}

				
			

Nous serons dirigés vers la vue `modificationProprio.html.twig` pour notre formulaire. Il est essentiel de noter que, malgré son nom, cette vue ne se limite pas uniquement à la modification. Nous l’utilisons également pour ajouter un nouveau propriétaire. Étant donné que l’objet `Proprietaires` n’est pas fourni dans ce cas, nous savons qu’il s’agit d’un ajout, ce qui signifie que le formulaire sera initialement vide, prêt à accueillir les informations du nouveau propriétaire.

				
					        if (!$lesProprio) {
            $lesProprio = new Proprietaires();
        }
        $form = $this->createForm(ProprioType::class, $lesProprio);
        $form->handleRequest($request);
				
			

Création de « form » qu’on va appeler dans la vue.

				
					            'form' => $form->createView(),

				
			
				
					        {{ form_start(form) }}
        {{ form_widget(form) }}
        <a class="btn-retour" href="{{ path('lesProprietairesAdmin') }}">Retour</a>

        <input type="submit" class="btn btn-primary btn-enregistrer" value="Enregistrer" />

        {{ form_end(form) }}
				
			

Résultat de notre formulaire

Note : Etant donné qu’on n’est pas dans la condition isModification, le titre sera Ajout d’un propriétaire.

Dans la base : Table Proprietaire avant

Ajout de données via formulaire...

Lorsque les données sont renseignées et validées, la variable `$manager` de la classe `EntityManagerInterface` joue un rôle clé. Elle permet de transférer les données collectées dans le formulaire, stockées temporairement dans la variable `$lesProprio`, vers la base de données. Ce processus garantit que toutes les informations saisies soient correctement enregistrées et gérées au sein de la base de données.

				
					        if ($form->isSubmitted() && $form->isValid()) {
            $manager->persist($lesProprio);
            $manager->flush();
            $this->addFlash('success', 'Action effectué avec succès!');
            return $this->redirectToRoute("lesProprietairesAdmin");
        }
				
			

Lorsque l’action est effectuée, un message est affiché pour confirmer visuellement à l’utilisateur que l’opération a été réalisée avec succès. Cela aide à fournir une réponse claire et immédiate, renforçant la convivialité de l’interface utilisateur.

Dans la base : Table Proprietaire après

Notre ajout a bien été effectué.

En résumé, le bouton AJOUTER nous redirige vers la fonction `ajoutEtModif()`, qui est conçue pour remplir deux fonctions simultanément. Si l’objet `propriétaire` est vide, cela signifie que le formulaire présenté sera également vide, indiquant qu’il s’agit d’un formulaire d’ajout pour un nouveau propriétaire. À l’inverse, si l’objet `propriétaire` contient déjà des données, le formulaire sera prérempli avec ces informations, transformant ainsi notre interaction en un formulaire de modification pour un propriétaire existant. Cela permet de passer aisément à l’étape de modification.

Modifier

La fonction MODIFIER fonctionne de manière similaire à AJOUTER, avec une différence principale : pour la modification, l'objet `Propriétaires` est déjà renseigné avec des données existantes. Ainsi, lorsque l'on clique sur MODIFIER dans la vue, on est redirigé vers `ajoutEtModif()`, tout comme pour l'ajout. Cependant, dans ce cas, le formulaire est prérempli avec les données du propriétaire existant, permettant une mise à jour plutôt que la création d'une nouvelle entrée.
				
					<form action="{{ path("admin_proprio_modification", {'id': leProprio.id}) }}" style="margin-right: 2px">
    <input type="submit" class="btn btn-outline-primary" value="MODIFIER">
</form>

				
			

Quand on souhaite modifier un propriétaire, il est important de se concentrer uniquement sur ses informations. Pour garantir cela, nous utilisons son identifiant unique spécifié dans le propriétaire. Lorsque l’utilisateur clique sur un propriétaire, son identifiant est récupéré via `leProprio.id`. Cet identifiant est essentiel pour cibler uniquement les données de ce propriétaire spécifique. Après que l’utilisateur a cliqué sur Modifier et que l’identifiant a été récupéré, il est redirigé vers le formulaire précédent. La différence est que le formulaire est déjà prérempli avec les données récupérées grâce à l’identifiant. La fonction `ajoutEtModif()` utilise la méthode GET pour récupérer l’identifiant du propriétaire, comme indiqué dans l’URL.

				
					            "isModification" => $lesProprio->getId() !== null

				
			

La variable `isModification` sert de signal pour indiquer qu’il s’agit d’une opération de modification, ce qui permet d’implémenter des conditions spécifiques dans notre code. Comme observé précédemment, cette variable est utilisée dans le code de notre vue. Lors d’une modification, le titre « Modification de Nom Prénom » est ajouté, clarifiant pour l’utilisateur qu’il est en train de mettre à jour les informations d’un propriétaire existant.

				
					          <h1>
            {% if isModification %}
              Modification de
              {{ proprio.nom }}
              {{ proprio.prenom }}
            {% else %}
              Ajout d'un propriétaire
            {% endif %}
          </h1>
				
			

Résultat

Oups, Alice aperçoit que son nom n’est pas « Durant » mais « Durand », modifions-le.

Table avant modification

Modification sur le formulaire...

Comme pour ajouter, une fois l’action est effectuée, un message est affiché.

Table après modification:

Durand a bien été modifié.

Supprimer

Pour finir, abordons la suppression. Cette étape est particulière car nous devrons également faire appel à des mesures de sécurité contre les attaques CSRF.
				
					<form action="{{ path("admin_proprio_modification", {'id': leProprio.id}) }}" style="margin-right: 2px">
    <input type="submit" class="btn btn-outline-primary" value="MODIFIER">
</form>

				
			

Pour se prémunir contre les attaques CSRF (Cross-Site Request Forgery), une menace où un attaquant peut amener un utilisateur légitime à effectuer des actions involontaires sur un site web, Symfony met en place un mécanisme de défense robuste. Lors de la création de formulaires, Symfony génère un jeton CSRF, un identifiant unique qui accompagne chaque formulaire. Ce jeton est impératif lors de la soumission du formulaire; il est vérifié pour authentifier que la requête provient bien de l’utilisateur attendu. Si le jeton est invalide ou absent, la soumission du formulaire est bloquée, empêchant ainsi l’exécution de l’action non désirée.

Pour activer cette protection dans Symfony, nous avons utilisé une commande spécifique qui configure et intègre la sécurité CSRF dans nos formulaires.

composer require symfony/security-bundle

Dans notre code sur le Template il nous reste le bouton supprimer à mettre en action, analysons ce bouton

				
					<form method="POST" action="{{ path('admin_proprio_suppression', { id: leProprio.id }) }}" onsubmit="return confirm('Un proprietaire va être supprimé, êtes vous sûr?')">
    <input type="hidden" name="_method" value="delete"/>
    <input type="hidden" name="_token" value="{{ csrf_token('SUP' ~ leProprio.id) }}"/>
    <input type="submit" class="btn btn-outline-danger" value="SUPPRIMER"/>
</form>

				
			

Lorsqu’on sélectionne l’option « Supprimer », la redirection se fait vers `admin_proprio_suppression`, qui déclenche à son tour la fonction `suppression()`. Le processus pour identifier le propriétaire spécifique à supprimer est similaire à celui utilisé pour la modification. En effet, nous récupérons également l’ID du propriétaire via la méthode GET. Cette méthode permet d’assurer que nous manipulons les données du bon propriétaire, en évitant toute action sur un mauvais enregistrement.

				
					    #[Route('/admin/proprietaire/supprimer/{id}', name: 'admin_proprio_suppression', methods:"delete")]
    public function suppression(Proprietaires $proprio=null, Request $request, EntityManagerInterface $manager): Response
    {
        if($this->isCsrfTokenValid("SUP".$proprio->getId(), $request->get('_token'))){
            $manager->remove($proprio);
            $manager->flush();
            $this->addFlash("success", "Suppression effectuée");
        }
        else{
            $this->addFlash("failed", "Suppression non effectuée");
        }
        return $this->redirectToRoute("lesProprietairesAdmin");      
    }
				
			

Après avoir récupéré l’ID du propriétaire, tout comme dans le processus de modification, nous appliquons une condition qui vérifie la validité du jeton CSRF. Cette étape est importante pour assurer la sécurité de l’opération en confirmant que la requête provient bien de l’utilisateur authentique et qu’elle n’est pas le résultat d’une manipulation externe. Si le jeton CSRF est valide, nous procédons à la suppression; dans le cas contraire, l’action est refusée pour prévenir toute action non autorisée.

				
					        if($this->isCsrfTokenValid("SUP".$proprio->getId(), $request->get('_token')))
				
			

Si le jeton CSRF est confirmé comme valide, nous procédons à la suppression de l’entité spécifiée en utilisant la variable `$manager` avec la méthode `remove()` pour marquer l’entité pour suppression. Une fois l’entité marquée, nous appelons la méthode `flush()` pour appliquer effectivement les modifications dans la base de données. Si cette opération se déroule sans accroc, un message de succès est alors affiché, informant l’utilisateur que la suppression a été effectuée avec succès.

				
					         $manager->remove($proprio);
            $manager->flush();
            $this->addFlash("success", "Suppression effectuée");
				
			

Sinon, un message d’échec est affiché.

				
					        else{
            $this->addFlash("failed", "Suppression non effectuée");
        }
				
			

Pour finir l’utilisateur est redirigé vers notre liste des propriétaires via lesProprietairesAdmin comme vue à la première étape.

				
					return $this->redirectToRoute("lesProprietairesAdmin");   
				
			

Pour un exemple, prenons pour cobaye Chloé.

Table avant suppression:

Il faut retenir que avant chaque suppression, notre interface affichera un message de confirmation à cette suppression.

				
													<form method="POST"  action="{{ path('admin_proprio_suppression', { id: leProprio.id })  }}"  onsubmit="return confirm('Un proprietaire va être supprimé, êtes vous sûr?')">

				
			

Une fois confirmé la suppression, un message comme pour les autres va s’afficher.

Table après suppression:

Durand a bien été modifié.

Pour conclure

La gestion des propriétaires dans notre application est structurée autour d’un processus clair et bien défini. Dès que l’administrateur se connecte, il a la possibilité de consulter les données des propriétaires, d’en ajouter de nouveaux, de modifier leurs informations existantes, et de supprimer ceux qui ne sont plus nécessaires. Cette suite d’actions assure une administration efficace et sécurisée des données des propriétaires au sein de l’application.

Fin

© Eren Varli