Gérer des utilisateurs sans FosUserBundle 3ème partie

Ici, nous allons mettre en place le changement de mot de passe. Pour cela, il va falloir faire évoluer nos services, créer un nouveau formulaire, mettre en place un event lors de la soumission du formulaire, un message flash… c’est parti!

Le changement de mot de passe

Commençons par créer notre entité ChangePassword.php.

Le formulaire

Le ChangePasswordController

Le template

Rajoutons le message flash de succès au niveau du template du dashboard:

Formidable, ça marche! Mais… ce n’est ni maintenable, ni codé en SOLID, ni même propre au final, quand on regarde notre contrôleur.

Quels sont les problèmes que nous avons ici:

  1. Pas de vérification que l’ancien mot de passe est correct
  2. Nous sommes ici fortement couplé à User, comme précédemment avec le formulaire d’inscription avant que nous ne créions un service utilisant le UserInterface
  3. Un contrôleur énorme qui fait beaucoup trop de choses: récupérer les valeurs, setter le plainPassword, encoder le nouveau mot de passe, flusher…

On va commencer à régler les problèmes un par un pour avoir un code qui sera fortement découplé.

Déléguer des tâches au UserManager

Nous allons définir deux fonctions ici:

  1. updateCredentials
  2. isPasswordValid

Pour cela, il nous faut passer un nouveau paramètre, UserPasswordEncoderInterface, pour faire appel à sa fonction isValidPassword (qui vérifie si l’ancien mot de passe de l’utilisateur est correct)

Faisons donc d’abord évoluer notre fichier services.xml:

puis notre UserManager:

Mise en place d’un event au niveau du ChangePasswordType

Déclaration de ChangePasswordType comme un service

Ce formulaire ayant à présent une dépendance, nous devons le déclarer comme un service:

Allègement de notre contrôleur

C’est un peu mieux, mais nous ne voulons pas dépendre du UserManager, bien entendu. Si l’on veut un jour changer le comportement, il faudra revenir sur le contrôleur. Comme pour l’enregistrement, nous allons créer un PasswordHandler qui implémentera notre FormHandlerInterface.

Vous l’avez compris, je veux arriver à ça:

Création du ChangePasswordFormHandler

 

Mise à jour du fichier des services:

Et voilà! Nous sommes parfaitement découplé et notre code est SOLID. Si l’envie nous prend  d’utiliser une autre action dans un contrôleur pour y passer un nouveau handler qui implémentera FormHandlerInterface, nous n’aurons pas à revenir sur du code existant mais à étendre le code. De même, si, par injection de dépendance, nous voulons que ce nouveau handler utilise non pas userManager mais un autre manager, si celui-ci implémente le UserManagerInterface, ça passera sans aucun souci.

Le code github se trouve ici: https://github.com/jpsymfony/authentication-demo
Sa version mise à jour (il faudra chercher un peu pour retrouver les classes car l’arborescence a changé) en Symfony 3.2 est ici: https://github.com/jpsymfony/symfony3-generic-project-symfony3-architecture

Rédigé par

2 comments

  1. Bonjour Jean Pierre,

    Merci pour les réponses aux questions, ta procédure est ingénieuse alors je veux toujours bien comprendre.
    Là je suis coincé sur ChangePasswordFormHandler avec le constructeur qui initialise UserManagerInterface $userManager.
    Un peu plus loin, dans la fonction handle, nous avons la condition avec
    $this->handler->updateCredentials($form->getData()->getUser(), $form->getData()->getNewPassword());
    Error /////////////////////////////////////////////////////////
    updateCredentials not found in UserManagerInterface, (affichée par phpstorm et exact) ce qui m’entraine dans cette issue avec l’erreur Call to a member function isPasswordValid() on null dans le formulaire de changement de mot de passe.

    Je suis un peu perdu, si tu peux m’aider.
    Merci Jean Pierre.

    1. Oui, il vaut mieux se baser sur la nouvelle version: https://github.com/jpsymfony/symfony3-generic-project-symfony3-architecture/blob/master/src/AppBundle/Entity/Manager/Interfaces/UserManagerInterface.php

      A l’époque, j’avais une classe UserManagerInterface incomplète. Dans la version Symfony3, elle est complète.

      Par contre, ça n’est pas lié à l’erreur du formulaire (c’est plus phpstorm qui va dire que la méthode est absente). Non, ici, c’est un souci d’injection / autowiring car symfony nous dit que le UserManager n’est pas injecté dans le constructeur du formulaire (si tu as voulu faire de l’autowiring, il faut déclarer l’alias de UserManagerInterface et dire qu’il doit injecter la classe UserManager), d’où l’erreur « Call to a member fonctionisPasswordValid() on null).

      Essaie de dumper le formulaire au moment où tu l’appelles pour voir mais je parierais ma chemise que le service n’est pas injecté, ce qui provoque l’erreur.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *