*
  • {value}: replaced with current value of the attribute.
  • * */ class EMongoUniqueValidator extends CValidator { /** * @var boolean whether the comparison is case sensitive. Defaults to true. * Note, by setting it to false, you are assuming the attribute type is string. */ public $caseSensitive = true; /** * @var boolean whether the attribute value can be null or empty. Defaults to true, * meaning that if the attribute is empty, it is considered valid. */ public $allowEmpty = true; /** * @var string the ActiveRecord class name that should be used to * look for the attribute value being validated. Defaults to null, meaning using * the class of the object currently being validated. * You may use path alias to reference a class name here. * @see attributeName */ public $className; /** * @var string the ActiveRecord class attribute name that should be * used to look for the attribute value being validated. Defaults to null, * meaning using the name of the attribute being validated. * @see className */ public $attributeName; /** * @var mixed additional query criteria. Either an array or CDbCriteria. * This will be combined with the condition that checks if the attribute * value exists in the corresponding table column. * This array will be used to instantiate a {@link CDbCriteria} object. */ public $criteria = array(); /** * @var string the user-defined error message. The placeholders "{attribute}" and "{value}" * are recognized, which will be replaced with the actual attribute name and value, respectively. */ public $message; /** * @var boolean whether this validation rule should be skipped if when there is already a validation * error for the current attribute. Defaults to true. */ public $skipOnError = true; /** * 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) { $value = $object->$attribute; if($this->allowEmpty && $this->isEmpty($value)){ return; } $className = $this->className === null ? get_class($object) : Yii::import($this->className); $attributeName = $this->attributeName === null ? $attribute : $this->attributeName; // We get a RAW document here to prevent the need to make yet another active record instance $doc = EMongoDocument::model($className) ->getCollection() ->findOne( array_merge( $this->criteria, array($attributeName => $this->caseSensitive ? $value : new MongoRegex('/' . $value . '/i')) ) ); // If a doc was found first test if the unique attribute is the primaryKey // If we are uniquely id'ing the pk then check this is a new record and not // an old one and check to see if the pks are the same // If the found doc is not evaledd onm pk then make sure the two pks are not the same if( $doc && ( ($attributeName === $object->primaryKey() && $object->getIsNewRecord() && (string)$doc[$object->primaryKey()] == (string)$object->getPrimaryKey()) || ((string)$doc[$object->primaryKey()] != (string)$object->getPrimaryKey()) ) ){ // Then it ain't unique $message = $this->message !== null ? $this->message : Yii::t('yii', '{attribute} "{value}" has already been taken.'); $this->addError($object, $attribute, $message, array('{value}' => CHtml::encode($value))); }else{} } }