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

Zend_Form PHP Discussion :

Validation de non-duplication de champs


Sujet :

Zend_Form PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Avatar de Janitrix
    Inscrit en
    Octobre 2005
    Messages
    3 391
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 3 391
    Par défaut Validation de non-duplication de champs
    Salut,

    Dans ce titre peu éloquent, je veux simplement dire que je voudrais vérifier qu'un champ ("nom" dans ce cas) n'existe pas déjà dans une table de ma base de données. Ma question est donc la suivante : dois-je réaliser cela avec un validateur et Zend_Form, ou, dois-je laisser cela à la base de données ?

    Le problème de la deuxième solution est la difficulté de récupérer un message compréhensible de la base de données, afin de prévenir l'utilisateur qu'un autre utilisateur dispose déjà du nom "John" par exemple.

    Que feriez-vous ?

    Merci.

  2. #2
    Membre éprouvé
    Avatar de Janitrix
    Inscrit en
    Octobre 2005
    Messages
    3 391
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 3 391
    Par défaut
    Bon j'ai fait un validateur fonctionnel.

    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
    50
    51
    52
    53
    54
    55
    56
    <?php
     
     
    class My_Validate_Db_Duplicate extends Zend_Validate_Abstract
    {
     
        const DUPLICATE = 'duplicate';
     
        /**
         * @var array
         */
        protected $_messageTemplates = array(
            self::DUPLICATE => "'%value%' est déjà enregistré."
        );
     
        protected $_source = null;
        protected $_field = null;
     
        /**
         * Sets validator options
         * @return void
         */
        function __construct($source, $field)
        {
     
            $reflector = new ReflectionClass($source);
     
            if (!$reflector->implementsInterface('Inuitech_Db_Source_Interface')) {
                throw new Exception('$source must implements Inuitech_Db_Source_Interface');
            }
     
            $this->_source = $source;
            $this->_field = $field;
        }
     
        /**
         * Defined by Zend_Validate_Interface
         *
         * Returns true if the value doesn't exist. 
         *
         * @param  mixed $value
         * @return boolean
         */
        public function isValid($value)
        {
        	$this->_setValue($value);
     
            if ($this->_source->exists($this->_field, $value)) {
                $this->_error();
                return false;
            }
     
            return true;
        }        
     
    }
    'Field' est le champ de la base de données à rechercher. 'Source' doit être une classe implémentant l'interface suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    <?php
     
    interface My_Db_Source_Interface
    {
     
        public function exists($field, $data);
     
    }
    Voici un exemple d'utilisation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $nom = new Zend_Form_Element_Text('nom');
            $nom->setRequired(true)
                ->addValidator(new Zend_Validate_StringLength(2, 32))
                ->addValidator(new Zend_Validate_Alnum(true))
                ->addValidator(new My_Validate_Db_Duplicate(new Membre(), 'nom'));
    'Membre' est une classe étendant Zend_Db_Table_Abstract, 'nom' est le champ de la base de données. Cela fonctionne bien mais je continue à me demander si cela n'est pas superflu sachant que la base de données fait déjà le boulot. Quoi qu'il en soit, je fais pour le moment ça car je peux avoir un message d'erreur en peu plus parlant pour l'utilisateur lambda.

    Ma question est toujours valable, si quelqu'un a une autre solution pour ce problème

  3. #3
    Expert confirmé
    Avatar de GrandFather
    Inscrit en
    Mai 2004
    Messages
    4 587
    Détails du profil
    Informations personnelles :
    Âge : 55

    Informations forums :
    Inscription : Mai 2004
    Messages : 4 587
    Par défaut
    C'est pas une mauvaise idée, mais j'y vois quand même un problème de granularité : tu t'exposes au cas où la validation passerait, mais que durant le laps de temps qui s'écoule entre la validation et l'exécution de l'insert un enregistrement soit créé (par un autre client) qui viole la règle d'unicité ; ton validateur n'est donc pas fiable à 100%.

    Personnellement, je fais un traitement a posteriori : j'analyse l'exception eventuellement levée lors de l'exécution d'une requête SQL (à l'aide d'une petite classe maison), et je renvoie au client un message d'erreur en conséquence. Par contre, évidemment, je me passe des décorateurs.
    FAQ XML
    ------------
    « Le moyen le plus sûr de cacher aux autres les limites de son savoir est de ne jamais les dépasser »
    Giacomo Leopardi

  4. #4
    Membre éprouvé
    Avatar de Janitrix
    Inscrit en
    Octobre 2005
    Messages
    3 391
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 3 391
    Par défaut
    J'ai étudié cette solution, mais comment fais-tu pour parser le message d'erreur de façon efficace ? Mon principale soucis était de récupérer le champ dupliqué responsable de l'erreur, car il n'est pas spécifié dans le message de l'erreur, et j'en ai besoin pour dire "le nom est dupliqué" ou "l'adresse email est dupliquée".

    Mais bien sur, cette manière de faire est la plus logique puisque c'est normalement le boulot du SGBD

  5. #5
    Expert confirmé
    Avatar de GrandFather
    Inscrit en
    Mai 2004
    Messages
    4 587
    Détails du profil
    Informations personnelles :
    Âge : 55

    Informations forums :
    Inscription : Mai 2004
    Messages : 4 587
    Par défaut
    Citation Envoyé par Janitrix Voir le message
    Mon principale soucis était de récupérer le champ dupliqué responsable de l'erreur, car il n'est pas spécifié dans le message de l'erreur, et j'en ai besoin pour dire "le nom est dupliqué" ou "l'adresse email est dupliquée".
    Le champ n'est pas spécifié, par contre le nom de la contrainte non respectée est précisé dans le message d'erreur (en tout cas pour PDO_PGSQL, je n'ai pas testé les autres). A partir du nom de la contrainte, il est facile de remonter jusqu'au champ concerné.

    Quant à l'extraction du nom de la contrainte violée dans le message d'erreur, une simple expression régulière fait l'affaire, surtout si tu as pris soin de choisir un préfixe pour le nom tes contraintes, du type ct_ ou chk_ par exemple. Après, tu n'as plus qu'à te servir du nom de la contrainte comme clé d'un tableau associatif (encapsulé par exemple dans la classe modèle de la table concernée) qui te donnera le message d'erreur à afficher dans la vue.

    Le défaut de cette approche, c'est qu'elle rend ta gestion d'erreur dépendante du formalisme employé par le SGBDR pour les messages d'erreur qu'il remonte, et donc du SGBDR lui-même. Mais comme il n'y pas de norme de gestion d'erreur vraiment établie entre tous les SGBDR, c'est inévitable.
    FAQ XML
    ------------
    « Le moyen le plus sûr de cacher aux autres les limites de son savoir est de ne jamais les dépasser »
    Giacomo Leopardi

  6. #6
    Membre éprouvé
    Avatar de Janitrix
    Inscrit en
    Octobre 2005
    Messages
    3 391
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 3 391
    Par défaut
    Citation Envoyé par GrandFather Voir le message
    Le défaut de cette approche, c'est qu'elle rend ta gestion d'erreur dépendante du formalisme employé par le SGBDR pour les messages d'erreur qu'il remonte, et donc du SGBDR lui-même. Mais comme il n'y pas de norme de gestion d'erreur vraiment établie entre tous les SGBDR, c'est inévitable.
    C'est un autre point qui m'avait gêné Merci de ta réponse, je n'étais pas sur. Je pense cependant rester avec ma solution pour le moment

    Merci encore

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 29/12/2014, 17h33
  2. Réponses: 7
    Dernier message: 03/05/2007, 16h30
  3. Réponses: 2
    Dernier message: 27/11/2006, 20h59
  4. Réponses: 5
    Dernier message: 29/08/2006, 17h30
  5. Validation CSS non conforme
    Par Mister Nono dans le forum Mise en page CSS
    Réponses: 1
    Dernier message: 18/08/2006, 09h01

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