Commit 31c24ec9 by Qiang Xue

Fixes #2003: Added `filter` property to `ExistValidator` and `UniqueValidator`…

Fixes #2003: Added `filter` property to `ExistValidator` and `UniqueValidator` to support adding additional filtering conditions
parent ec663c36
......@@ -69,6 +69,7 @@ Yii Framework 2 Change Log
- Enh #1921: Grid view ActionColumn now allow to name buttons like `{controller/action}` (creocoder)
- Enh #1973: `yii message/extract` is now able to generate `.po` files (SergeiKutanov, samdark)
- Enh #1984: ActionFilter will now mark event as handled when action run is aborted (cebe)
- Enh #2003: Added `filter` property to `ExistValidator` and `UniqueValidator` to support adding additional filtering conditions (qiangxue)
- Enh: Added `favicon.ico` and `robots.txt` to default application templates (samdark)
- Enh: Added `Widget::autoIdPrefix` to support prefixing automatically generated widget IDs (qiangxue)
- Enh: Support for file aliases in console command 'message' (omnilight)
......
......@@ -54,6 +54,13 @@ class ExistValidator extends Validator
* If the key and the value are the same, you can just specify the value.
*/
public $targetAttribute;
/**
* @var string|array|\Closure additional filter to be applied to the DB query used to check the existence of the attribute value.
* This can be a string or an array representing the additional query condition (refer to [[\yii\db\Query::where()]]
* on the format of query condition), or an anonymous function with the signature `function ($query)`, where `$query`
* is the [[\yii\db\Query|Query]] object that you can modify in the function.
*/
public $filter;
/**
......@@ -72,8 +79,6 @@ class ExistValidator extends Validator
*/
public function validateAttribute($object, $attribute)
{
/** @var \yii\db\ActiveRecordInterface $targetClass */
$targetClass = $this->targetClass === null ? get_class($object) : $this->targetClass;
$targetAttribute = $this->targetAttribute === null ? $attribute : $this->targetAttribute;
if (is_array($targetAttribute)) {
......@@ -92,8 +97,11 @@ class ExistValidator extends Validator
}
}
$targetClass = $this->targetClass === null ? get_class($object) : $this->targetClass;
$query = $this->createQuery($targetClass, $params);
/** @var \yii\db\ActiveRecordInterface $className */
if (!$targetClass::find()->where($params)->exists()) {
if (!$query->exists()) {
$this->addError($object, $attribute, $this->message);
}
}
......@@ -113,10 +121,20 @@ class ExistValidator extends Validator
throw new InvalidConfigException('The "targetAttribute" property must be configured as a string.');
}
/** @var \yii\db\ActiveRecordInterface $targetClass */
$targetClass = $this->targetClass;
$query = $targetClass::find();
$query->where([$this->targetAttribute => $value]);
$query = $this->createQuery($this->targetClass, [$this->targetAttribute => $value]);
return $query->exists() ? null : [$this->message, []];
}
protected function createQuery($targetClass, $condition)
{
/** @var \yii\db\ActiveRecordInterface $targetClass */
$query = $targetClass::find()->where($condition);
if ($this->filter instanceof \Closure) {
call_user_func($this->filter, $query);
} elseif ($this->filter !== null) {
$query->andWhere($this->filter);
}
return $query;
}
}
......@@ -51,6 +51,13 @@ class UniqueValidator extends Validator
* If the key and the value are the same, you can just specify the value.
*/
public $targetAttribute;
/**
* @var string|array|\Closure additional filter to be applied to the DB query used to check the uniqueness of the attribute value.
* This can be a string or an array representing the additional query condition (refer to [[\yii\db\Query::where()]]
* on the format of query condition), or an anonymous function with the signature `function ($query)`, where `$query`
* is the [[\yii\db\Query|Query]] object that you can modify in the function.
*/
public $filter;
/**
* @inheritdoc
......@@ -91,6 +98,12 @@ class UniqueValidator extends Validator
$query = $targetClass::find();
$query->where($params);
if ($this->filter instanceof \Closure) {
call_user_func($this->filter, $query);
} elseif ($this->filter !== null) {
$query->andWhere($this->filter);
}
if (!$object instanceof ActiveRecordInterface || $object->getIsNewRecord()) {
// if current $object isn't in the database yet then it's OK just to call exists()
$exists = $query->exists();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment