【问题标题】:CakePHP 3 Multiple isUnique allowing NULL duplicateCakePHP 3 Multiple isUnique 允许 NULL 重复
【发布时间】:2016-03-16 09:35:45
【问题描述】:

我的 BlockedTable.php 中有以下规则

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

    return $rules;
}

到目前为止,这一切都很好 - 如果我尝试使用已经存在的日期和时间保存新记录,它会阻止我保存。

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

╔════╦══════════════╦═══════╗
║ ID ║  Date        ║ Time  ║
╠════╬══════════════╬═══════╣
║  1 ║ 22/08/1985   ║ NULL  ║
╚════╩══════════════╩═══════╝

该规则仍然允许我保存具有相同数据的新条目。因此,如果我尝试保存 $date = 22/08/1985$time = NULL 它保存得很好,并且我的数据库中有重复记录。由于上述规则,我预计它会失败吗?

为什么会这样?以及如何防止 NULL 值上的重复条目?

提前感谢您的帮助。

【问题讨论】:

标签: php validation cakephp cakephp-3.0


【解决方案1】:

使用普通比较运算符与NULL 比较,即column = NULL(唯一规则所做的),应始终为NULL(AFAIK,至少在 MySQL 和 Postgres 中是这种情况),因此没有找到,因此只要涉及 NULL 值,唯一检查就会通过。

如果您想阻止这种行为,您必须使用自定义规则,因为内置规则根本不支持它。我认为这是值得改进的东西,所以你可能想开一张票over at 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);
}

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

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

另见

【讨论】:

  • 感谢 ndm 的深入回答,我会考虑我的选择,同时创建一个增强票。
  • 刚刚做了自定义规则,并且运行良好。再次感谢
【解决方案2】:

我知道这是一篇旧帖子,但是由于我必须进行大量搜索才能解决这个问题,我想我应该在这里发布我是如何做到的。

在 cakePHP 3.6 中,您可以通过将 isUnique 类中的属性 allowMultipleNulls 更改为 false 来解决此问题。

问候。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-20
    • 2012-08-16
    • 2018-01-23
    • 1970-01-01
    相关资源
    最近更新 更多