IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Symfony PHP Discussion :

Validation données formulaire | Utilisation d'un callback, service ? [2.x]


Sujet :

Symfony PHP

  1. #1
    Membre à l'essai Avatar de MaolmeoX
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2016
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2016
    Messages : 11
    Points : 12
    Points
    12
    Par défaut Validation données formulaire | Utilisation d'un callback, service ?
    Bonjour à tous,

    Je suis actuellement en stage.

    Dans mon application Symfony j'utilise FOSUser pour gérer les utilisateurs, à l'inscription de l'utilisateur j'ai ajouté un champ que je nomme "Code Client".

    L'utilisateur remplit ce champ s'il a déjà un compte chez nous.

    Quand on soumet le formulaire d'inscription, je veux pouvoir faire une requête dans une autre base de données qui me permet de comparer si l'adresse mail qu'il a saisit ainsi que le code client existent et correspondent dans notre base de données CRM avant de push l'entité User vers la base qui gère l'application.

    Pour cela, j'ai créé un callback dans mon Entité User

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    <?php
     
    // src/AppBundle/Entity/User.php
     
    namespace UserBundle\Entity;
     
    use FOS\UserBundle\Model\User as BaseUser;
    use Doctrine\ORM\Mapping as ORM;
    use Symfony\Component\Validator\Constraints as Assert;
    use Symfony\Component\Validator\Context\ExecutionContextInterface;
     
    /**
     * @ORM\Entity
     * @ORM\Table(name="fos_user")
     */
    class User extends BaseUser {
        /**
         * @Assert\Callback
         */
        public function validate(ExecutionContextInterface $context) {
            $email = $this->getEmail();        
     
            $sql = "SELECT  comp_codecomptable FROM vEntityPhoneEmailPerson WHERE Pers_EmailAddress=:mail";
            $em = $this>getDoctrine()->getEntityManager('crm');
            $connection = $em->getConnection();
            $statement = $connection->prepare($sql);
            $statement->bindValue(':mail', $mail);
            $statement->execute();
            $tabResult = $statement->fetchAll(PDO::FETCH_OBJ);
     
            dump($tabResult);
     
            $userCodeClient = $this->getUserCodeClient();
     
            if ($email != $userCodeClient) {
                $context->buildViolation("Votre code client ne correspond pas au mail référencé dans notre base de données, veuillez laisser le champ vide si vous n'avez pas de compte client")
                        ->atPath('userCodeClient')
                        ->addViolation();
            }
        }
     
        /**
         * @var string   
         * 
         * @ORM\Column(name="userCodeClient", type="string", length=255, nullable=true)
         * 
         */
        private $userCodeClient;
    }
    En fait je souhaiterais pouvoir effectuer une requête, sauf que je ne peux pas appeler l'entity manager depuis ma class User car $this correspond à une instance de ma classe User et que ma class étend déjà BaseUser donc je ne peux pas étendre Controller.

    Pour ce qui est du test bidon qui consiste à comparer le mail au code client, s'était juste pour tester que ma validation est fonctionnel et que ça m'affiche bien un message d'erreur près de mon formulaire quand on veut le valider.



    Mes questions:

    1) Est-ce qu'utiliser un Callback est la bonne solution ?

    1.1) Si non, qu'est ce que vous me conseillez de faire ?


    2) Comment décomposer mon problème pour pouvoir exécuter une requête ?

    (Sachant que la requête que je souhaite faire n'est liée à aucune entité présente dans mon application, je veux juste checker une information dans une vue de mon autre base et si c'est okay je valide l'inscription du nouvel utilisateur).


    Si vous souhaitez de plus ample informations n'hésitez pas et merci de prendre le temps de me répondre.

  2. #2
    Membre expert
    Avatar de dukoid
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2012
    Messages
    2 100
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2012
    Messages : 2 100
    Points : 3 004
    Points
    3 004
    Par défaut
    Une entité ne doit pas avoir une telle responsabilité.

    Etant donné que tu veux valider ou pas l'inscription sur un critère personnel tu es obligé de surcharger le controller register de fosUserBundle.
    et avec Symfony c'est très simple :
    tu insères proprement ton code avant l'enregistrement. (en utilisant un service perso par ex)
    http://symfony.com/doc/current/bundl...ntrollers.html

  3. #3
    Membre à l'essai Avatar de MaolmeoX
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2016
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2016
    Messages : 11
    Points : 12
    Points
    12
    Par défaut
    Bonjour Dukoid et merci pour ta réponse.

    Ce matin en arrivant je me suis dis que j'allais créer un service que j'allais charger dans le registrationController, jusque là tout fonctionne parfaitement, le seul soucis c'est que ça ne m'affiche pas un texte prêt de mon champ qui contient une erreur.

    Je met quand même le code de mon service au cas où ça peut aider quelqu'un.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    <?php
     
    namespace UserBundle\Validator;
     
    use \PDO;
     
    class codeClient {
     
        public function __construct($doctrine) {
            $this->em = $doctrine->getManager('crm');
        }
     
        /**
         * Vérifie si le code client existe en base
         *
         * @param string $codeClient
         * @return bool
         */
        public function isCodeClient($mail, $codeClient) {
     
            $sql = "SELECT  comp_codecomptable FROM vEntityPhoneEmailPerson WHERE Pers_EmailAddress=:mail";
            $em = $this->em;
            $connection = $em->getConnection();
            $statement = $connection->prepare($sql);
            $statement->bindValue(':mail', $mail);
            $statement->execute();
            $tabCodeComptable = $statement->fetchAll(PDO::FETCH_OBJ);
     
            $codeCompte = trim($tabCodeComptable[0]->comp_codecomptable);
     
            return $codeCompte == $codeClient;
        }
     
    }
    Ensuite il faut penser à déclarer son service dans le dossier AcmeBundle/Ressources/config/parameters.yml

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    services:    
        user.codeClient:
            class:     UserBundle\Validator\codeClient
            arguments: [@doctrine]
    A partir de là je me suis dis que j'allais faire autrement et créer quelque chose qui me semble un peu plus propre, une contrainte de validation personnalisée avec injection de dépendances (doctrine).

    J'ai donc créé ma classe ContainsCodeClient

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    <?php
     
    namespace UserBundle\Validator\Constraints;
     
    use Symfony\Component\Validator\Constraint;
     
    /**
     * @Annotation
     */
    class ContainsCodeClient extends Constraint {
     
        public $message = "";
        public $entity;
        public $property;
     
        public function validatedBy() {
            return 'validator.codeClient.exist';
        }
     
        public function requiredOptions() {
            return array('entity', ' property');
        }
     
        public function targets() {
            return self::PROPERTY_CONSTRAINT;
        }
     
    }
    Et le validator qui va avec et qui porte le nom de ContainsCodeClientValidator:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    <?php
     
    namespace UserBundle\Validator\Constraints;
     
    use Doctrine\ORM\EntityManager;
    use Symfony\Component\Validator\Constraint;
    use Symfony\Component\Validator\ConstraintValidator;
    use \PDO;
     
    class ContainsCodeClientValidator extends ConstraintValidator {
     
        public function __construct($doctrine) {
            $this->em = $doctrine->getManager('crm');
        }
     
        public function validate($value, Constraint $constraint) {
    //        On vérifie si la personne a rempli le champ sur lequel on a mit la contrainte dans notre entité
            if (!empty($value)) {
    //            On récupère le mail que l'utilisateur a saisi pour nous permettre d'effectuer notre requête
                $mail = $this->context->getObject()->getEmail();
                $sql = "SELECT  comp_codecomptable FROM vEntityPhoneEmailPerson WHERE Pers_EmailAddress=:mail";
                $connection = $this->em->getConnection();
                $statement = $connection->prepare($sql);
                $statement->bindValue(':mail', $mail);
                $statement->execute();
                $tabCodeComptable = $statement->fetchAll(PDO::FETCH_OBJ);
    //            Si on récupère un résultat on le traite
                if (!empty($tabCodeComptable)) {
                    $codeCompte = trim($tabCodeComptable[0]->comp_codecomptable);
    //                On compare si le code client du formulaire est différent de celui de la base CRM
                    if ($value != $codeCompte) {
                        $this->context->buildViolation("Votre code client ne correspond pas au mail référencé dans notre base de données, veuillez laisser le champ vide si vous n'avez pas de compte client")
                                ->atPath('userCodeClient')
                                ->addViolation();
                    }
    //                Si le form renvoi un code client qui n'existe pas en base CRM on déclenche une erreur 
                } elseif (empty($tabCodeComptable)) {
                    $this->context->buildViolation("Votre code client ne correspond pas au mail référencé dans notre base de données, veuillez laisser le champ vide si vous n'avez pas de compte client")
                            ->atPath('userCodeClient')
                            ->addViolation();
                }
            }
        }
    }
    Déclaration dans le services.yml du bundle:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    services:
     
        user.validator.constraints.contains.code.client.validator.class:
            class: UserBundle\Validator\Constraints\ContainsCodeClientValidator
            arguments: [@doctrine]
            tags:
                - { name: validator.constraint_validator, alias: validator.codeClient.exist }
    Mon code fonctionne, un utilisateur arrive à s'inscrire sans code client pour avoir accès a une version simplifié de l'application et ils peuvent accéder à une version plus complète en mettant leur code client.

    Je ne sais pas si mon code est correct et respect les bonnes pratiques, notamment concernant la méthode que j'utilise pour récupérer une information du formulaire.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $mail = $this->context->getObject()->getEmail();
    Si vous avez des suggestions d'améliorations, etc. je suis preneur.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 6
    Dernier message: 15/05/2007, 17h27
  2. [Formulaire]validation données zone de texte
    Par Lex O'Mil dans le forum IHM
    Réponses: 5
    Dernier message: 24/03/2007, 12h51
  3. Effacer données formulaire sans utiliser de bouton
    Par GillesFABRE dans le forum ASP
    Réponses: 3
    Dernier message: 23/08/2006, 13h27
  4. [WebForms]Comment utiliser la touche entrée pour valider un formulaire ?
    Par yonialhadeff dans le forum Général Dotnet
    Réponses: 3
    Dernier message: 10/05/2006, 12h29
  5. Réponses: 6
    Dernier message: 06/01/2006, 10h17

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo