yii:如何为两个属性制定唯一规则

yii:如何为两个属性制定唯一规则,yii,yii1.x,yii-validation,Yii,Yii1.x,Yii Validation,我有一张这样的桌子: (id、名称、版本、文本)。 (名称、版本)是唯一键,我如何制定规则来验证此项。可能是您可以将此规则添加到您的代码中 return array( array('name', 'unique', 'className'=>'MyModel', 'attributeName'=>'myName'), array('version', 'unique', 'className'=>'MyModel', 'attributeName'=>'m

我有一张这样的桌子: (id、名称、版本、文本)。
(名称、版本)是唯一键,我如何制定规则来验证此项。

可能是您可以将此
规则添加到您的代码中

return array(
    array('name', 'unique', 'className'=>'MyModel', 'attributeName'=>'myName'),
    array('version', 'unique', 'className'=>'MyModel', 'attributeName'=>'myVersion')
);

这可以由Yii自己完成,您不需要扩展它。 但是,扩展可以帮助清理
rules()
方法,如下所述:

这是代码(从该站点复制),它将在不使用扩展名的情况下工作:

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

如果
$this->secondKey
的值在
rules()
-方法中不可用,您可以在CActiveRecords
beforeValidate()
-方法中添加验证器,如下所示:

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;
}

您不需要rules()方法的复杂内容,也不需要第三方扩展。只需创建自己的验证方法。你自己做会容易得多

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");
  }

}

他们在下一个候选版本Yii1.14rc中增加了对独特组合键的支持,但这里有一个(另一个)解决方案。顺便说一句,这段代码在规则中使用了与Yii框架在下一个正式版本中使用的相同的“attributeName”

protected/models/Mymodel.php

    public function rules()
    {
        return array(
            array('name', 'uniqueValidator','attributeName'=>array(
              'name', 'phone_number','email') 
        ),
...
  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.');
        }
    }

}
'application.components.validators.*',
  • 规则开头的“name”是验证错误将附加到的属性,稍后将输出到表单上
  • “attributeName”(数组)包含要作为组合键一起验证的键数组
protected/components/validators/uniqueValidator.php

    public function rules()
    {
        return array(
            array('name', 'uniqueValidator','attributeName'=>array(
              'name', 'phone_number','email') 
        ),
...
  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.');
        }
    }

}
'application.components.validators.*',
您可以使用任意数量的属性,这将适用于所有CModel。使用“exists”完成检查

protected/config/main.php

    public function rules()
    {
        return array(
            array('name', 'uniqueValidator','attributeName'=>array(
              'name', 'phone_number','email') 
        ),
...
  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.');
        }
    }

}
'application.components.validators.*',
您可能需要在“导入”数组中将上述行添加到配置中,以便Yii应用程序可以找到uniqueValidator.php


积极的反馈和改变是非常欢迎的

这很容易。在数组中,包括在扩展类中创建的参数

下一个代码在模型内部

array('name', 'ext.ValidateNames', 'with'=>'lastname')
下一个代码来自class
ValidateNames
,进入extensions文件夹

class ValidateNames extends CValidator
{
    public $with=""; /*my parameter*/

    public function validateAttribute($object, $attribute)
    {
        $temp = $this->with;  
        $lastname = $object->$temp;
        $name = $object->$attribute;
        $this->addError($object,$attribute, $usuario." hola ".$lastname);
    }
}
Yii1:

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']]
在Yii2中:

public function rules() {
    return [
        [['name'], 'unique', 'targetAttribute' => ['name', 'version']],
    ];
}

基于上面的函数,这里有一个函数可以添加到ActiveRecord模型中

你会像这样使用它

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;
}
array(array('productname,productversion'),'ValidateUniqueColumns','Product已包含该版本'),
/*
*验证属性的唯一性,包括多个属性
*/
公共函数ValidateUniqueColumns($attributes,$params)
{
$columns=分解(“,”,$attributes);
//创建SQL语句
$select_criteria=“”;
$column\u count=计数($columns);
$lastcolumn=“”;
对于($index=0;$indexdb->quoteValue($this->getAttribute($columns[$index]));
$column_equals=“”..$columns[$index]”“`=“.$value.”;
$select_criteria=$select_criteria.$column_等于;
$select_criteria=$select_criteria.“;
如果($index+1<$column\u count)
{
$select_criteria=$select_criteria.“和”;
}
}
$select_criteria=$select_criteria.”和“`.”“$this->getTableSchema()->primaryKey.”“`”.Yii::app()->db->quoteValue($this->getAttribute($this->getTableSchema()->primaryKey))”;
$SQL=“选择COUNT(`.$this->getTableSchema()->>primaryKey.`)作为`.'''.$this->tableName().`中的`.$SELECT\\\\\条件;
$list=Yii::app()->db->createCommand($SQL)->queryAll();
$total=intval($list[0][“计数”]);
如果($total>0)
{
$this->addError($lastcolumn,$params[0]);
返回false;
}
返回true;
}

这将只验证名称是否唯一,版本是否唯一。它不会验证这对列(名称、版本)
。我尝试了这个方法,但是我没有得到值
$this->secondKey
$this->secondKey
应该是第二个必须唯一的属性。你必须根据属性名调整它。我知道。我尝试了我的属性名。我不仅仅是在
规则()
谢谢。我会检查一下。顺便说一句,我最后编写了一个自定义验证器方法。+1用于解决规则()中没有secondKey的情况。这就解决了我的问题。您的答案不包含任何其他答案中至少一个尚未提供的信息。我仍在使用1.13版本的大型应用程序,但我没有时间升级。通过快速测试,这非常有效,谢谢!它还避免了创建自定义验证程序(当然不难,但可能会变得混乱)并解决了将动态值作为第二个属性传递的一些问题(可能会变得非常混乱)。