mirror of
https://github.com/yiisoft/yii2.git
synced 2025-08-26 14:26:54 +08:00
Fixes #13704: Fixed yii\validators\UniqueValidator
to prefix attribute name with model's database table name
This commit is contained in:

committed by
Alexander Makarov

parent
b00cd65ef3
commit
3c1f3e20cf
@ -50,6 +50,7 @@ Yii Framework 2 Change Log
|
||||
- Bug #4408: Add support for unicode word characters and `+` character in attribute names (sammousa, kmindi)
|
||||
- Bug #10372: Fixed console controller including complex typed arguments in help (sammousa)
|
||||
- Bug #13738: Fixed `getQueryParams()` method in `yii.js` to correctly parse URL with question mark and no query parameters (vladdnepr)
|
||||
- Bug #13704: Fixed `yii\validators\UniqueValidator` to prefix attribute name with model's database table name (vladis84)
|
||||
|
||||
2.0.11.2 February 08, 2017
|
||||
--------------------------
|
||||
|
@ -10,9 +10,9 @@ namespace yii\validators;
|
||||
use Yii;
|
||||
use yii\base\Model;
|
||||
use yii\db\ActiveQuery;
|
||||
use yii\db\ActiveRecord;
|
||||
use yii\db\ActiveQueryInterface;
|
||||
use yii\db\ActiveRecordInterface;
|
||||
use yii\db\Query;
|
||||
use yii\helpers\Inflector;
|
||||
|
||||
/**
|
||||
@ -119,7 +119,7 @@ class UniqueValidator extends Validator
|
||||
public function validateAttribute($model, $attribute)
|
||||
{
|
||||
/* @var $targetClass ActiveRecordInterface */
|
||||
$targetClass = $this->targetClass === null ? get_class($model) : $this->targetClass;
|
||||
$targetClass = $this->getTargetClass($model);
|
||||
$targetAttribute = $this->targetAttribute === null ? $attribute : $this->targetAttribute;
|
||||
$rawConditions = $this->prepareConditions($targetAttribute, $model, $attribute);
|
||||
$conditions[] = $this->targetAttributeJunction === 'or' ? 'or' : 'and';
|
||||
@ -141,6 +141,15 @@ class UniqueValidator extends Validator
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Model $model the data model to be validated
|
||||
* @return string Target class name
|
||||
*/
|
||||
private function getTargetClass($model)
|
||||
{
|
||||
return $this->targetClass === null ? get_class($model) : $this->targetClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the $model exists in the database.
|
||||
*
|
||||
@ -234,9 +243,22 @@ class UniqueValidator extends Validator
|
||||
$conditions = [$targetAttribute => $model->$attribute];
|
||||
}
|
||||
|
||||
if (!$model instanceof ActiveRecord) {
|
||||
return $conditions;
|
||||
}
|
||||
|
||||
// Add table prefix for column
|
||||
$targetClass = $this->getTargetClass($model);
|
||||
$tableName = $targetClass::tableName();
|
||||
$conditionsWithTableName = [];
|
||||
foreach ($conditions as $columnName => $columnValue) {
|
||||
$prefixedColumnName = "{$tableName}.$columnName";
|
||||
$conditionsWithTableName[$prefixedColumnName] = $columnValue;
|
||||
}
|
||||
|
||||
return $conditionsWithTableName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and adds [[comboNotUnique]] error message to the specified model attribute.
|
||||
* @param \yii\base\Model $model the data model.
|
||||
|
@ -331,6 +331,32 @@ abstract class UniqueValidatorTest extends DatabaseTestCase
|
||||
$result = $this->invokeMethod(new UniqueValidator(), 'prepareConditions', [$targetAttribute, $model, $attribute]);
|
||||
$expected = ['val_attr_b' => 'test value b', 'val_attr_c' => 'test value a'];
|
||||
$this->assertEquals($expected, $result);
|
||||
|
||||
// Add table prefix for column name
|
||||
$model = Profile::findOne(1);
|
||||
$attribute = 'id';
|
||||
$targetAttribute = 'id';
|
||||
$result = $this->invokeMethod(new UniqueValidator(), 'prepareConditions', [$targetAttribute, $model, $attribute]);
|
||||
$expected = [Profile::tableName() . '.' . $attribute => $model->id];
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
public function testGetTargetClassWithFilledTargetClassProperty()
|
||||
{
|
||||
$validator = new UniqueValidator(['targetClass' => Profile::className()]);
|
||||
$model = new FakedValidationModel();
|
||||
$actualTargetClass = $this->invokeMethod($validator, 'getTargetClass', [$model]);
|
||||
|
||||
$this->assertEquals(Profile::className(), $actualTargetClass);
|
||||
}
|
||||
|
||||
public function testGetTargetClassWithNotFilledTargetClassProperty()
|
||||
{
|
||||
$validator = new UniqueValidator();
|
||||
$model = new FakedValidationModel();
|
||||
$actualTargetClass = $this->invokeMethod($validator, 'getTargetClass', [$model]);
|
||||
|
||||
$this->assertEquals(FakedValidationModel::className(), $actualTargetClass);
|
||||
}
|
||||
|
||||
public function testPrepareQuery()
|
||||
|
Reference in New Issue
Block a user