【问题标题】:CakePHP 3.x unique validation not working for saving multiple recordsCakePHP 3.x 唯一验证不适用于保存多条记录
【发布时间】:2017-01-19 00:08:29
【问题描述】:

我有一个Questions 表,它的验证如下:

$validator
    ->notEmpty('title')
    ->add('title', [
        'unique' => [
            'rule' => [
                    'validateUnique', 
                     ['scope' => ['subject_id', 'chapter_id']]
            ],
            'provider' => 'table'
        ]
    ]);

我想一次将以下记录保存到我的表中。

Array
(
    [0] => Array
        (
            [subject_id] => 1
            [chapter_id] => 4
            [title] => What is a .ctp file used for in CakePHP?
        )
    [1] => Array
        (
            [subject_id] => 1
            [chapter_id] => 4
            [title] => What is a .ctp file used for in CakePHP?
        )
)

我尝试使用saveMany() 方法保存它。它保存了两条记录,即验证不起作用。我也尝试使用transactional() 方法而不是saveMany() 方法的代码,但验证也不起作用。

$entities = $this->Questions->newEntities($records);
$this->Questions->connection()->transactional(function () use ($entities) {
    foreach ($entities as $entity) {
       $this->Questions->save($entity);
    }
});

如果我使用save() 方法一一保存记录,或者我的记录已经保存在数据库中,我的验证工作正常。为什么我的唯一验证不适用于 saveMany()transactional() 重复的新实体?

【问题讨论】:

    标签: validation cakephp cakephp-3.0


    【解决方案1】:

    验证发生在之前保存

    验证发生在保存之前,因此这种行为是意料之中的,因为规则查找的是数据库,而不是请求数据(它只能在无论如何,时间),即无论有多少数据集正在测试,都不会保存提交的数据集,因此除非数据库中已经存在匹配的记录,否则验证将通过。

    因此,要么在自定义事务中一一创建/修补和保存所有实体(并且不要忘记添加一些适当的故障检查),

    $this->Questions->connection()->transactional(function () {
        foreach ($this->request->data() as $set) {
            $entity = $this->Questions->newEntity($set); // < validaton is being applied there
            if (!$this->Questions->save($entity)) { // < not there
                return false;
            }
        }
        return true;
    });
    

    或改用应用程序规则。

    保存过程中正在应用应用规则

    应用程序规则正在实际保存过程中应用,即在调用Table::save() 时,因此为了避免使用自定义事务的麻烦,并且通常有最后一道防线,请使用它们来代替/附加到验证。

    // QuestionsTable class
    
    public function buildRules(\Cake\ORM\RulesChecker $rules)
    {
        $rules->add($rules->isUnique(['title', 'subject_id', 'chapter_id']));
    
        // ...
    
        return $rules;
    }
    

    另见

    【讨论】:

    • 如果我按照您的建议使用transactional() 方法,那么这两个中只有一条记录保存在数据库中。如果我根据您的建议使用构建规则和我的transactional(),那么这两个都不会保存在数据库中。
    • 如果我按照您对 transactional() 的建议使用构建规则,那么一切正常。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    相关资源
    最近更新 更多