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