在Yii2中,我的数据库中有两个字段:email
和shopId
Email
和shopId
应该unique
在一起Email
也可以是empty
(NULL
),而shopId
始终是整数这些是我在模型中的规则:
[['email'],'default','value' => NULL],
[['shopId'], 'integer'],
[['email','shopId'], 'unique', 'targetAttribute' => ['email', 'shopId'], 'message' => 'Already taken!'],
如果我有两个条目,例如,这不起作用email="NULL"
和shopId="1"
。
我该如何解决这个问题?
答案 0 :(得分:2)
将false
属性设置为jmap -dump:file=heapdump.hprof,format=b
http://www.yiiframework.com/doc-2.0/yii-validators-validator.html# $ skipOnEmpty-detail
答案 1 :(得分:2)
虽然您的解决方案正常运行但技术上并不正确。 验证规则
[['email','shopId'], 'unique', 'targetAttribute' => ['email', 'shopId']]
如果email
不为空(所需功能),将验证shopId
对于给定email
是唯一的,但它也会验证shopId
在给定email
时是唯一的{1}}如果shopId
不为空(不需要)。您正在使用两个查询来验证两个字段。
符合您需求的验证规则是
[['email'], 'unique', 'targetAttribute' => ['email', 'shopId']]
说“如果email
不为空,请检查email
和shopId
的组合是否唯一,并将结果绑定到email
属性”。
答案 2 :(得分:0)
我在规则
中使用了when条件[
['email', 'shopId'],
'unique',
'targetAttribute' => ['email', 'shopId'],
'message' => 'Diese E-Mail Adresse ist bereits registriert!',
'when' => function ($model) {
return !empty($model->email);
}
],
答案 3 :(得分:0)
我已经创建了一个解决方案来强制跨一组字段的唯一性,包括可空字段,它在可以简单地放入任何 Yii2 模型的通用 PHP Trait 中利用 yii\validators\UniqueValidator::$filter 回调。完整代码示例如下:
通用特征 [common/models/traits/UniqueValidatorFilterTrait.php]
<?php
namespace common\models\traits;
use yii\db\ActiveQuery;
/**
* Trait UniqueValidatorFilterTrait provides custom anonymous function callback methods.
*
* @package common\models\traits
* @author Alec Pritchard <ajmedway@gmail.com>
*/
trait UniqueValidatorFilterTrait
{
/**
* Custom anonymous function for [[yii\validators\UniqueValidator::$filter]], used to modify the passed-in
* [[\yii\db\ActiveRecord]] query to be applied to the DB query used to check the uniqueness of the input value.
*
* @param ActiveQuery $query
* @param array $nullableUniqueFields the field names to ensure are considered and validated for the uniqueness
* of a set of model attributes, even if some have empty/null values.
* @see \yii\validators\UniqueValidator::$filter
*/
public function filterFunctionUniqueWithNull(ActiveQuery $query, array $nullableUniqueFields = [])
{
// check if at least one of the $nullableUniqueFields currently has an empty value loaded
$hasEmptyUniqueField = false;
foreach ($nullableUniqueFields as $field) {
if (empty($this->{$field})) {
$hasEmptyUniqueField = true;
break;
}
}
// proceed to modify AR query
if ($hasEmptyUniqueField) {
// change query item for the $nullableUniqueFields, which only checks against empty string by design
// @link https://github.com/yiisoft/yii2/issues/4333#issuecomment-57739619
// ensure the composite unique constraint is applied to include NULL values for all $nullableUniqueFields
foreach ($query->where as $whereItemKey => $whereItem) {
if (!is_array($whereItem)) continue;
foreach ($whereItem as $columnName => $value) {
// check if this column is one of the unique fields and if it currently has an empty string
if (str_replace($nullableUniqueFields, '', $columnName) != $columnName
&& $value === '') {
// change from '' to NULL
$query->where[$whereItemKey][$columnName] = null;
}
}
}
}
}
}
示例模型使用
<?php
namespace common\models;
use Yii;
use common\models\traits\UniqueValidatorFilterTrait;
/**
* This is the model class for table "my_table".
*
* @property int $id
* @property null|string $email
* @property int $shop_id
*/
class MyTable extends \yii\db\ActiveRecord
{
use UniqueValidatorFilterTrait;
/**
* {@inheritdoc}
*/
public static function tableName()
{
return 'my_table';
}
/**
* {@inheritdoc}
*/
public function rules()
{
return [
[
['email', 'shop_id'],
'unique',
'targetAttribute' => ['email', 'shop_id'],
// ensure the composite unique constraint is applied to include NULL values for specified nullable fields
'filter' => function (MyTableQuery $query) {
/* @see \common\models\traits\UniqueValidatorFilterTrait::filterFunctionUniqueWithNull() */
$this->filterFunctionUniqueWithNull($query, ['email', 'shop_id']);
},
// ensure that we don't skip on empty values, namely the `email` and/or `shop_id`
'skipOnEmpty' => false,
],
];
}
查看关于 Yii2 核心唯一验证器的这个缺点的完整讨论,以及核心开发团队给出的原因:https://github.com/yiisoft/yii2/issues/4333