CakePHP 3多个isUnique允许NULL重复

Jay*_*mon 5 php validation cakephp cakephp-3.0

我的BlockedTable.php中有以下规则

public function buildRules(RulesChecker $rules)
{
    $rules->add($rules->isUnique(['date', 'time']),
        ['message' => 'unique error']);

    return $rules;
}
Run Code Online (Sandbox Code Playgroud)

到目前为止,这已经运行良好 - 如果我尝试使用已有的日期和时间保存新记录,它会阻止我保存.

但是,如果我的时间是NULL,如下面的条目;

?????????????????????????????
? ID ?  Date        ? Time  ?
?????????????????????????????
?  1 ? 22/08/1985   ? NULL  ?
?????????????????????????????
Run Code Online (Sandbox Code Playgroud)

该规则仍允许我使用相同的数据保存新条目.因此,如果我尝试保存$date = 22/08/1985$time = NULL保存正常,并且我的数据库中存在重复记录.由于上述规则,我原本预计会失败吗?

为什么会这样?如何防止重复输入NULL值?

在此先感谢您的帮助.

ndm*_*ndm 2

NULL与使用普通比较运算符进行比较,即column = NULL(唯一规则所做的),应该始终是NULL(AFAIK 至少在 MySQL 和 Postgres 中是这种情况),因此什么也找不到,因此只要存在NULL涉及的价值。

如果您想防止这种行为,则必须使用自定义规则,因为内置规则根本不支持它。我认为这是值得改进的地方,因此您可能需要在 GitHub 上开票。

这是覆盖规则类的基本示例IsUnique,它基本上只是IS向条件键添加一个运算符,以便NULL检查最终为column IS NULL.

public function __invoke(EntityInterface $entity, array $options)
{
    if (!$entity->extract($this->_fields, true)) {
        return true;
    }

    $alias = $options['repository']->alias();
    $conditions = $this->_alias($alias, $entity->extract($this->_fields));
    if ($entity->isNew() === false) {
        $keys = (array)$options['repository']->primaryKey();
        $keys = $this->_alias($alias, $entity->extract($keys));
        if (array_filter($keys, 'strlen')) {
            $conditions['NOT'] = $keys;
        }
    }

    // handle null values
    foreach ($conditions as $key => $value) {
        if ($value === null) {
            $conditions[$key . ' IS'] = $value;
            unset($conditions[$key]);
        }
    }

    return !$options['repository']->exists($conditions);
}
Run Code Online (Sandbox Code Playgroud)

理论上,您也可以在重写IsUnique::_alias()方法中执行此操作,该方法无需重新实现原始规则类中的代码即可工作,但这并不是真正正确的位置。

https://github.com/cakephp/cakephp/blob/3.2.5/src/ORM/Rule/IsUnique.php

也可以看看