Zend FR

Consultez la FAQ sur le ZF avant de poster une question

Vous n'êtes pas identifié.

#1 20-08-2010 15:38:48

Dede
Membre
Date d'inscription: 26-06-2009
Messages: 99

Validateur_Db sur champs multiple

Bonjour,
J'essaie de plus en plus d'utiliser les validateurs de Zend, notamment pour les formulaires.
Je suis tombé sur un cas où il me fallait un validateur qui vérifie la présence de plusieurs valeurs dans la table.
N'ayant pas réussit à le faire avec les validateurs standard, j'ai adapté Zend_Validate_Db_NoRecordExists.

Je pense que cela peut être utile à d'autres... donc le voici :

Code:

<?php
/**
 * Zend Framework Addon
 *
 * Addon to be used in the 'My' Library, performs a DataBase test
 * on multiple fields. Used with Zend_From return the Error message
 * if all values match.
 * As to be integrated on the first element of the array.
 *
 * @category   Zend
 * @package    My_Validate_Db
 *
 */
 
require_once 'Zend/Validate/Abstract.php';

class My_Validate_Db_MultiFields extends Zend_Validate_Abstract
{
    /**
     * Error constants
     */
    const ERROR_RECORD_FOUND    = 'recordFound';

    /**
     * @var array Message templates
     */
    protected $_messageTemplates = array(
        self::ERROR_RECORD_FOUND    => "A record matching '%value%' was found",
    );

    /**
     * @var string
     */
    protected $_table = '';

    /**
     * @var array
     */
    protected $_fields = array();

    /**
     * @var string
     */
    protected $_subformExt = false;

    /**
     * Database adapter to use. If null isValid() will use Zend_Db::getInstance instead
     *
     * @var unknown_type
     */
    protected $_adapter = null;

    /**
     * Confirms a record exists in a table on mutiple field.
     * Fields array :
     *      array(
     *          'field_1',
     *          'field_2',...)
     *
     * @param  TableName(string) $table
     * @param  FieldList(array) $fields
     * @return void
     */

    public function __construct($table, $fields)
    {
            $options['table'] = $table;
            $options['fields'] = $fields;

        if (!array_key_exists('table', $options) && !array_key_exists('schema', $options)) {
            require_once 'Zend/Validate/Exception.php';
            throw new Zend_Validate_Exception('Table or Schema option missing!');
        }

        if (!array_key_exists('fields', $options)) {
            require_once 'Zend/Validate/Exception.php';
            throw new Zend_Validate_Exception('Field option missing!');
        }

        if (!is_array($options['fields'])) {
            require_once 'Zend/Validate/Exception.php';
            throw new Zend_Validate_Exception('Field option must be an array!');
        }

        $this->setFields($options['fields']);
        $this->_table = (string) $options['table'];
    }

    public function setFields($options)
    {
        foreach($options as $v){
            $this->_fields[] = (string) $v;
        }
    }

    /**
     * Run query and returns matches, or null if no matches are found.
     *
     * @param  Array $values
     * @return Array when matches are found.
     */
    protected function _query($values)
    {
        /**
         * Check for an adapter being defined. if not, fetch the default adapter.
         */
        if ($this->_adapter === null) {
            $this->_adapter = Zend_Db_Table_Abstract::getDefaultAdapter();
            if (null === $this->_adapter) {
                require_once 'Zend/Validate/Exception.php';
                throw new Zend_Validate_Exception('No database adapter present');
            }
        }

        /**
         * Build select object
         */
        $select = new Zend_Db_Select($this->_adapter);
        $select->from($this->_table, $this->_fields);

        foreach ($values as $k => $v)
            $select->where($this->_adapter->quoteIdentifier($k).' = ?', $v);

        $select->limit(1);
        /**
         * Run query
         */
        $result = $this->_adapter->fetchRow($select);

        return $result;
    }

    public function isValid($value, $context = null)
    {
        $valid = true;

        /**
         * Set (array)$values to be sent to query
         */
        $values = array($this->_fields[0] => $value);
        for ($i=1;$i < count($this->_fields);$i++)
            $values[$this->_fields[$i]] = $context[$this->_fields[$i]];

        /**
         * Put all fields nam into %value%
         */
        $this->_setValue(implode(', ', $values));

        $result = $this->_query($values);
        if ($result) {
            $valid = false;
            $this->_error(self::ERROR_RECORD_FOUND);
        }

        return $valid;
    }

}

localisation : library/My/Validate/Db/MultiFields.php
Utilisation:
Pour unformulaire

Code:

$nom = new Zend_Form_Element_Text('nom');
$nom->setLabel('Nom')
    ->addValidator( new My_Validate_Db_MultiFields('users', array('nom','prenom')))
    ->setRequired();

$prenom = new Zend_Form_Element_Text('prenom');
$prenom->setLabel('Prénom')
       ->setRequired();

ou librement

Code:

$validator = new My_Validate_Db_MultiFields('foo',array('ch1','ch2','ch3'));
if($validator->isValid($valueCh1, array($valueCh2, $valueCh3)))
/**
 * N'est pas présent dans la table
 */
}else{
/**
 * Est déjà enregistré
 */
}

Revoie le message d'erreur dans le cas où le "couple" nom/prenom est présent dans la base.
Peut être rapidement adapté pour la vérification de la répétition de mot de passe et, bien sûr amélioré.

Dernière modification par Dede (22-08-2010 12:16:16)


« Il ne faut pas lier un navire à une seule ancre, ni une vie à un seul espoir. »
Epictète
http://www.noumcreation.com

Hors ligne

 

#2 24-08-2010 14:42:31

Kaiowas
Membre
Date d'inscription: 03-08-2009
Messages: 49

Re: Validateur_Db sur champs multiple

Merci pour ce code qui, après quelques modifications (pour l'adapter à mon code), s'avère fonctionner !

Hors ligne

 

#3 24-08-2010 18:56:40

Dede
Membre
Date d'inscription: 26-06-2009
Messages: 99

Re: Validateur_Db sur champs multiple

De rien, c'est le principe smile


« Il ne faut pas lier un navire à une seule ancre, ni une vie à un seul espoir. »
Epictète
http://www.noumcreation.com

Hors ligne

 

#4 25-08-2010 10:55:29

Kaiowas
Membre
Date d'inscription: 03-08-2009
Messages: 49

Re: Validateur_Db sur champs multiple

Je suis d'accord mais bon merci ça coute rien, et puis ça m'a fait gagner du temps ^^'

Hors ligne

 

#5 30-08-2010 10:40:16

Dede
Membre
Date d'inscription: 26-06-2009
Messages: 99

Re: Validateur_Db sur champs multiple

Bonjour,
Cette fois j'ai une question sur mon propre validateur...
Lorsque je le déclare je procède de la manière suivante :

Code:

$element = Zend_Form_Element_text('foo')
$element->setLabel('Foo')
             ->addValidator(new My_Validate_Db_MultiFields('ma_table', array('champ1', 'champ2')));

Mais pour l'update il bloque puisque, effectivement, le "couple" champ1 & champ2 est déjà présent...
Alors j'aimerais le déclarer de cette façon pour pouvoir utiliser la méthode removeValidator('Db_MultiFields'):

Code:

...
->addValidator('Db_MultiFields', false, array('ma_table', array('champ1', 'champ2')));
...

Mais cela ne fonctionne pas car il ne trouve pas le validateur perso.
Est il possible de le déclarer pour que cela fonctionne?

J'ai explorer deux piste (qui fonctionne) :
- Ajouter le validateur dans le cas d'un insert
- Ajouter un teste sur la présence de l'id dans le validateur ?

Mais je souhaiterais savoir si ma première démarche est possible/bonne ?


« Il ne faut pas lier un navire à une seule ancre, ni une vie à un seul espoir. »
Epictète
http://www.noumcreation.com

Hors ligne

 

#6 06-09-2010 14:43:15

Kaiowas
Membre
Date d'inscription: 03-08-2009
Messages: 49

Re: Validateur_Db sur champs multiple

J'avais même pas fait attention ! Du coup je fais des modifications aussi..

La 1ère solution est à éviter, le validateur va être totalement inactif si tu fais un update, du coup tu pourras mettre un "couple champ1/champ2" qui pourrait déjà être enregistré dans la base. Je pense plutôt sur la solution 2 (j'y travaille)

Hors ligne

 

#7 06-09-2010 15:34:19

Kaiowas
Membre
Date d'inscription: 03-08-2009
Messages: 49

Re: Validateur_Db sur champs multiple

OK, c'est bon. Il faut rajouter un attribut dans la classe (l'id de la ligne à modifier). Si elle est remplie, il faut rajouter une condition "clé primaire<>id" dans la méthode _query, et le tour est joué !

Hors ligne

 

Pied de page des forums

Propulsé par PunBB
© Copyright 2002–2005 Rickard Andersson
Traduction par punbb.fr

Graphisme réalisé par l'agence Rodolphe Eveilleau
Développement par Kitpages