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 ...@@ -69,6 +69,7 @@ Yii Framework 2 Change Log
- Enh #1921: Grid view ActionColumn now allow to name buttons like `{controller/action}` (creocoder) - 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 #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 #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 `favicon.ico` and `robots.txt` to default application templates (samdark)
- Enh: Added `Widget::autoIdPrefix` to support prefixing automatically generated widget IDs (qiangxue) - Enh: Added `Widget::autoIdPrefix` to support prefixing automatically generated widget IDs (qiangxue)
- Enh: Support for file aliases in console command 'message' (omnilight) - Enh: Support for file aliases in console command 'message' (omnilight)
......
...@@ -54,6 +54,13 @@ class ExistValidator extends Validator ...@@ -54,6 +54,13 @@ class ExistValidator extends Validator
* If the key and the value are the same, you can just specify the value. * If the key and the value are the same, you can just specify the value.
*/ */
public $targetAttribute; 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 ...@@ -72,8 +79,6 @@ class ExistValidator extends Validator
*/ */
public function validateAttribute($object, $attribute) 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; $targetAttribute = $this->targetAttribute === null ? $attribute : $this->targetAttribute;
if (is_array($targetAttribute)) { if (is_array($targetAttribute)) {
...@@ -92,8 +97,11 @@ class ExistValidator extends Validator ...@@ -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 */ /** @var \yii\db\ActiveRecordInterface $className */
if (!$targetClass::find()->where($params)->exists()) { if (!$query->exists()) {
$this->addError($object, $attribute, $this->message); $this->addError($object, $attribute, $this->message);
} }
} }
...@@ -113,10 +121,20 @@ class ExistValidator extends Validator ...@@ -113,10 +121,20 @@ class ExistValidator extends Validator
throw new InvalidConfigException('The "targetAttribute" property must be configured as a string.'); throw new InvalidConfigException('The "targetAttribute" property must be configured as a string.');
} }
/** @var \yii\db\ActiveRecordInterface $targetClass */ $query = $this->createQuery($this->targetClass, [$this->targetAttribute => $value]);
$targetClass = $this->targetClass;
$query = $targetClass::find();
$query->where([$this->targetAttribute => $value]);
return $query->exists() ? null : [$this->message, []]; 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 ...@@ -51,6 +51,13 @@ class UniqueValidator extends Validator
* If the key and the value are the same, you can just specify the value. * If the key and the value are the same, you can just specify the value.
*/ */
public $targetAttribute; 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 * @inheritdoc
...@@ -91,6 +98,12 @@ class UniqueValidator extends Validator ...@@ -91,6 +98,12 @@ class UniqueValidator extends Validator
$query = $targetClass::find(); $query = $targetClass::find();
$query->where($params); $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 (!$object instanceof ActiveRecordInterface || $object->getIsNewRecord()) {
// if current $object isn't in the database yet then it's OK just to call exists() // if current $object isn't in the database yet then it's OK just to call exists()
$exists = $query->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