web-dev-qa-db-fra.com

yii: comment créer une règle unique pour deux attributs

J'ai un tableau comme celui-ci:.

34
li meirong

Cela peut être fait par Yii lui-même, vous n'avez pas besoin d'une extension pour cela . Cependant, une extension peut aider à nettoyer la méthode rules() comme décrit ici:

http://www.yiiframework.com/extension/unique-attributes-validator/

C'est le code (copié depuis ce site) qui fonctionnera sans utiliser l'extension:

public function rules() {
    return array(
        array('firstKey', 'unique', 'criteria'=>array(
            'condition'=>'`secondKey`=:secondKey',
            'params'=>array(
                ':secondKey'=>$this->secondKey
            )
        )),
    );
}

Si la valeur de $this->secondKey n'est pas disponible dans la méthode rules()-, vous pouvez ajouter le validateur dans la méthode CActiveRecords beforeValidate()- comme ceci:

public function beforeValidate()
{
    if (parent::beforeValidate()) {

        $validator = CValidator::createValidator('unique', $this, 'firstKey', array(
            'criteria' => array(
                'condition'=>'`secondKey`=:secondKey',
                'params'=>array(
                    ':secondKey'=>$this->secondKey
                )
            )
        ));
        $this->getValidatorList()->insertAt(0, $validator); 

        return true;
    }
    return false;
}
50
cebe

Vous n'avez pas besoin du contenu compliqué de la méthode rules () ni des extensions tierces. Créez simplement votre propre méthode de validation. C'est beaucoup plus facile de le faire vous-même.

public function rules()
{
  return array(
    array('firstField', 'myTestUniqueMethod'),
  );
}

public function myTestUniqueMethod($attribute,$params)
{

   //... and here your own pure SQL or ActiveRecord test ..
   // usage: 
   // $this->firstField;
   // $this->secondField;
   // SELECT * FROM myTable WHERE firstField = $this->firstField AND secondField = $this->secondField ...
   // If result not empty ... error

  if (!$isUnique)
  {
    $this->addError('firstField', "Text of error");
    $this->addError('secondField', "Text of error");
  }

}
8
Racky

Yii1:

http://www.yiiframework.com/extension/composite-unique-key-validatable/

Yii2:

// a1 needs to be unique
['a1', 'unique']
// a1 needs to be unique, but column a2 will be used to check the uniqueness of the a1 value
['a1', 'unique', 'targetAttribute' => 'a2']
// a1 and a2 need to be unique together, and they both will receive error message
[['a1', 'a2'], 'unique', 'targetAttribute' => ['a1', 'a2']]
// a1 and a2 need to be unique together, only a1 will receive error message
['a1', 'unique', 'targetAttribute' => ['a1', 'a2']]
// a1 needs to be unique by checking the uniqueness of both a2 and a3 (using a1 value)
['a1', 'unique', 'targetAttribute' => ['a2', 'a1' => 'a3']]

http://www.yiiframework.com/doc-2.0/yii-validators-uniquevalidator.html

5
sj59

Ils ont ajouté la prise en charge de clés composites uniques dans la prochaine version candidate de Yii1.14rc, mais voici (encore une autre) solution. En passant, ce code utilise le même 'attributName' dans les règles que le framework Yii utilisera dans la prochaine version officielle.

protected/models/Mymodel.php

    public function rules()
    {
        return array(
            array('name', 'uniqueValidator','attributeName'=>array(
              'name', 'phone_number','email') 
        ),
...
  • 'nom' au début de la règle est l'attribut auquel l'erreur de validation sera jointe et ultérieurement affiché sur votre formulaire. 
  • 'attributNom' (tableau) contient un tableau de clés que vous souhaitez valider ensemble en tant que clé combinée.

protected/components/validators/uniqueValidator.php

  class uniqueValidator extends CValidator
    {
        public $attributeName;
        public $quiet = false; //future bool for quiet validation error -->not complete
    /**
     * Validates the attribute of the object.
     * If there is any error, the error message is added to the object.
     * @param CModel $object the object being validated
     * @param string $attribute the attribute being validated
     */
    protected function validateAttribute($object,$attribute)
    {
        // build criteria from attribute(s) using Yii CDbCriteria
        $criteria=new CDbCriteria();
        foreach ( $this->attributeName as $name )
            $criteria->addSearchCondition( $name, $object->$name, false  );

        // use exists with $criteria to check if the supplied keys combined are unique
        if ( $object->exists( $criteria ) ) {
            $this->addError($object,$attribute, $object->label() .' ' .
              $attribute .' "'. $object->$attribute . '" has already been taken.');
        }
    }

}

Vous pouvez utiliser autant d'attributs que vous le souhaitez et cela fonctionnera pour tous vos CModels. La vérification est faite avec "existe". 

protected/config/main.php

'application.components.validators.*',

Vous devrez peut-être ajouter la ligne ci-dessus à votre configuration dans le tableau "import" afin que le fichier uniqueValidator.php soit trouvé par l'application Yii.

Les retours positifs et les changements sont les bienvenus!

4
Jesse C

En Yii2:

public function rules() {
    return [
        [['name'], 'unique', 'targetAttribute' => ['name', 'version']],
    ];
}
4
Antonín Slejška

En fonction de la fonction ci-dessus, voici une fonction que vous pouvez ajouter à votre modèle ActiveRecord.

Vous l'utiliseriez comme ça,

array( array('productname,productversion'), 'ValidateUniqueColumns', 'Product already contains that version'),


/*
 * Validates the uniqueness of the attributes, multiple attributes
 */
public function ValidateUniqueColumns($attributes, $params)
{
    $columns = explode(",", $attributes);
    //Create the SQL Statement
    $select_criteria = "";
    $column_count = count($columns);
    $lastcolumn = "";

    for($index=0; $index<$column_count; $index++)
    {
        $lastcolumn = $columns[$index];
        $value = Yii::app()->db->quoteValue( $this->getAttribute($columns[$index]) );
        $column_equals = "`".$columns[$index]."` = ".$value."";
        $select_criteria = $select_criteria.$column_equals;
        $select_criteria = $select_criteria."  ";
        if($index + 1 < $column_count)
        {
            $select_criteria = $select_criteria." AND ";
        }
    }

    $select_criteria = $select_criteria." AND `".$this->getTableSchema()->primaryKey."` <> ".Yii::app()->db->quoteValue($this->getAttribute( $this->getTableSchema()->primaryKey ))."";

    $SQL = " SELECT COUNT(`".$this->getTableSchema()->primaryKey."`) AS COUNT_ FROM `".$this->tableName()."` WHERE ".$select_criteria;

    $list = Yii::app()->db->createCommand($SQL)->queryAll();
    $total = intval( $list[0]["COUNT_"] );

    if($total > 0)
    {
        $this->addError($lastcolumn, $params[0]);
        return false;
    }

    return true;
}
0
Mnyikka