【问题标题】:yii: how to make a unique rule for two attributesyii:如何为两个属性制定唯一规则
【发布时间】:2012-03-29 02:01:07
【问题描述】:

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

【问题讨论】:

    标签: yii yii1.x yii-validation


    【解决方案1】:

    也许您可以将此rules 添加到您的代码中

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

    【讨论】:

    • 这只会验证名称是唯一的并且版本是唯一的。它不会验证(name, version) 的列对。
    【解决方案2】:

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

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

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

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

    【讨论】:

    • 我试过这个方法,但我没有得到值$this->secondKey
    • $this->secondKey 应该是第二个必须唯一的属性。您必须将其调整为您的属性名称。
    • 我知道。我尝试使用我的属性名称。我不只是在rules() 中获取属性的值
    • 谢谢。我会查一下。顺便说一句,我最终编写了一个自定义验证器方法。
    • +1 用于解决第二个密钥在 rules() 中不可用的情况。这解决了我的问题。
    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

      他们在 Yii1.14rc 的下一个候选版本中添加了对唯一复合键的支持,但这里是(又一个)解决方案。顺便说一句,此代码在 Yii 框架将在下一个正式版本中使用的规则中使用相同的“attributeName”。

      protected/models/Mymodel.php

          public function rules()
          {
              return array(
                  array('name', 'uniqueValidator','attributeName'=>array(
                    'name', 'phone_number','email') 
              ),
      ...
      
        规则开头的
      • 'name' 是验证错误将附加到并稍后输出到您的表单的属性。
      • 'attributeName'(数组)包含一个键数组,您希望将它们作为组合键一起验证。

      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.');
              }
          }
      
      }
      

      您可以使用任意数量的属性,这将适用于您的所有 CModel。检查是用“存在”完成的。

      protected/config/main.php

      'application.components.validators.*',
      

      您可能需要将上述行添加到“import”数组中的配置中,以便 Yii 应用程序可以找到 uniqueValidator.php。

      非常欢迎积极的反馈和更改!

      【讨论】:

      • 我仍然在 1.13 上,因为我没有时间升级一个相当大的应用程序。通过快速测试,这很好用,谢谢!它还避免了必须创建自定义验证器(不难,授予但可能会变得混乱),并解决了将动态值作为第二个属性传递的一些问题(可能会真的变得混乱)。
      【解决方案5】:

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

      下一个代码在模型内部。

      array('name', 'ext.ValidateNames', 'with'=>'lastname')
      

      下一个代码来自 ValidateNames 类的扩展文件夹。

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

      【讨论】:

      • 您的答案不包含至少其他答案之一尚未提供的任何信息。
      【解决方案6】:

      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

      【讨论】:

        【解决方案7】:

        在 Yii2 中:

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

        【讨论】:

          【解决方案8】:

          基于上面的函数,这里有一个可以添加到 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;
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-12-24
            • 1970-01-01
            • 2019-10-05
            • 2021-12-19
            • 1970-01-01
            相关资源
            最近更新 更多