我拥有的
我的 belongsToMany 关联类似于CakePHP Cookbook中的关联,但是我在标记标题上设置了UNIQUE
约束。
(另一个可能无关紧要的区别是,我在 Tags 表中的每个标签旁边添加了一个site_id
字段,并且在tag
和site_id
上设置了另一个复合UNIQUE
约束。)
不起作用的地方
提交重复的标记标题会导致错误。
当我在保存新的 Article 实体之前调试它时,我可以看到重复的标记标题在验证尝试后被拒绝。
'tags' => [
// This submitted tag title already exists in Tags
(int) 0 => object(App\Model\Entity\Tag) id:1 {
'site_id' => (int) 2
'[new]' => true
'[accessible]' => [
'site_id' => true,
'title' => true,
'created' => true,
'modified' => true,
'site' => true,
'articles' => true,
]
'[dirty]' => [
'site_id' => true,
]
'[original]' => [
]
'[virtual]' => [
]
'[hasErrors]' => true
'[errors]' => [
'title' => [
'unique' => 'The provided value is invalid', // ← error
],
]
'[invalid]' => [
'title' => 'test',
]
'[repository]' => 'Tags'
},
// …
// This submitted tag title does *not* already exist in Tags
(int) 3 => object(App\Model\Entity\Tag) id:4 {
'title' => 'tag'
'site_id' => (int) 2
'[new]' => true
'[accessible]' => [
'site_id' => true,
'title' => true,
'created' => true,
'modified' => true,
'site' => true,
'articles' => true,
]
'[dirty]' => [
'title' => true, // ← no error
'site_id' => true,
]
'[original]' => [
]
'[virtual]' => [
]
'[hasErrors]' => false
'[errors]' => [
]
'[invalid]' => [
]
'[repository]' => 'Tags'
},
]
我期望它如何工作?
我所寻找的行为是,如果一个标签已经存在,那么就取它的ID,然后把提交的文章条目链接到这个现有的ID。
是否有一个标志,我错过了,将告诉/允许ORM这样做,或者我也许应该开始尝试一些->epilog()
技巧?
1条答案
按热度按时间gpnt7bae1#
ORM保存过程没有这样的功能,并且您不能将
epilog()
与默认的ORMsave()
过程一起使用,您必须实际手动创建插入查询,但是您不能真正使用实体,并且它也不能解决验证问题,和应用程序规则(您不希望盲目地将数据插入到插入查询中,即使Query::values()
绑定数据也是如此)。我可能会建议检查一下在编组之前修改数据的解决方案是否合适,它将透明地集成到过程中。您可以使用唯一索引列来查找现有的行,并将它们的主键值注入到请求数据中,然后修补/编组过程将能够正确地查找现有的记录并相应地更新它们。
根据具体的使用情况,这可能比手动构造插入查询要多做一些工作,但IMHO集成起来会更好。在您的特定情况下,这可能更容易,因为使用手动插入查询需要您分别为所有不同的表插入数据,因为您不能使用ORM的关联保存功能和手动构造的插入查询。
最后,这里有一些未经测试的快速和肮脏的示例代码来说明这个概念:
通过注入现有记录的主键,编组、验证、规则和保存应该能够正确区分要更新的内容和要插入的内容,即,您应该能够继续使用默认的ORM保存过程,就像您习惯的那样。
另请参阅
*Cookbook〉数据库访问和ORM〉保存数据〉在构建实体之前修改请求数据
*Cookbook〉数据库访问和ORM〉查询生成器〉插入数据
*操作手册〉数据库访问和ORM〉表对象〉生命周期回调〉beforeMarshal