CakePHP 3.x唯一验证不适用于保存多个记录

时间:2016-09-11 10:54:14

标签: validation cakephp cakephp-3.0

我有一个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()的重复新实体?

1 个答案:

答案 0 :(得分:2)

在保存

之前验证

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

因此,要么在自定义事务中逐个创建/补丁并保存所有实体(并且不要忘记添加一些正确的失败检查),

$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;
}

另见