/** * Checks whether the $model exists in the database. * * @param string $targetClass the name of the ActiveRecord class that should be used to validate the uniqueness * of the current attribute value. * @param array $conditions conditions, compatible with [[\yii\db\Query::where()|Query::where()]] key-value format. * @param Model $model the data model to be validated * * @return bool whether the model already exists */ private function modelExists($targetClass, $conditions, $model) { /** @var ActiveRecordInterface $targetClass $query */ $query = $this->prepareQuery($targetClass, $conditions); if (!$model instanceof ActiveRecordInterface || $model->getIsNewRecord() || $model->className() !== $targetClass::className()) { // if current $model isn't in the database yet then it's OK just to call exists() // also there's no need to run check based on primary keys, when $targetClass is not the same as $model's class $exists = $query->exists(); } else { // if current $model is in the database already we can't use exists() /** @var $models ActiveRecordInterface[] */ $models = $query->select($targetClass::primaryKey())->limit(2)->all(); $n = count($models); if ($n === 1) { $keys = array_keys($conditions); $pks = $targetClass::primaryKey(); sort($keys); sort($pks); if ($keys === $pks) { // primary key is modified and not unique $exists = $model->getOldPrimaryKey() != $model->getPrimaryKey(); } else { // non-primary key, need to exclude the current record based on PK $exists = reset($models)->getPrimaryKey() != $model->getOldPrimaryKey(); } } else { $exists = $n > 1; } } return $exists; }