CakePHP 使用 saveAll:如何使用 HABTM 链接记录保存额外数据?
Posted
技术标签:
【中文标题】CakePHP 使用 saveAll:如何使用 HABTM 链接记录保存额外数据?【英文标题】:CakePHP using saveAll: How do I save extra data with the HABTM link record? 【发布时间】:2011-02-26 21:44:29 【问题描述】:我已经能够使用 Cakephp 的 saveAll 方法同时创建“成员”并将它们注册到一个“事件”中(创建 HABTM 链接记录),这太棒了。例如,此代码创建了两个新的“成员”,并将每个人的记录添加到“EventsMember”表中,将它们注册为“事件”10:
$data = array(
'0' => array(
'Member' => array('email' => 'nobody@nowhere.com'),
'Event' => array('id' => 10)
),
'1' => array(
'Member' => array('email' => 'somebody@nowhere.com'),
'Event' => array('id' => 10)
)
);
$this->Member->saveAll($data);
但是,“EventsMember”表中的记录还有一个名为“role”的字段,其中包含“Presenter”或“Host”或“Attendee”之类的内容,我想在创建关系时保存这些数据。我试过了,但它不起作用(“EventsMember”“角色”字段始终为空白):
$data = array(
'0' => array(
'Member' => array('email' => 'nobody@nowhere.com'),
'Event' => array('id' => 10),
'EventsMember' => array('role' => 'Host')
),
'1' => array(
'Member' => array('email' => 'somebody@nowhere.com'),
'Event' => array('id' => 10),
'EventsMember' => array('role' => 'Attendee')
)
);
$this->Member->saveAll($data);
我想知道这是否可能,是否可能我必须使用某种回调,如 beforeSave 或 afterSave 来完成这项工作?我读到在使用 saveAll 时这些回调存在一些问题,因此我正在寻找有关最佳实践的任何提示。
谢谢!
编辑:我听取了 Adam 的建议,并对我的模型进行了以下更改:
// Event.php
var $hasMany = array('EventsMember');
// Member.php
var $hasMany = array('EventsMember');
// EventsMember.php
var $belongsTo = array('Event', 'Member');
然后在我的控制器中,我的代码看起来与我的第二个示例几乎相同,除了我从 EventsMember
模型中调用了 saveAll()
方法,如文档中所述:
$data = array(
'0' => array(
'Member' => array('email' => 'nobody@nowhere.com'),
'Event' => array('id' => 10),
'EventsMember' => array('role' => 'Host')
),
'1' => array(
'Member' => array('email' => 'somebody@nowhere.com'),
'Event' => array('id' => 10),
'EventsMember' => array('role' => 'Attendee')
)
);
$this->EventsMember->saveAll($data);
结果是根本没有保存Member
或EventsMember
记录。我尝试从Member
模型($this->Member->saveAll($data);
)触发保存,这保存了Member
记录,但没有加入EventsMember
记录。
我尝试删除预先存在的 HABTM 关联,但没有任何区别。 EventsMember
模型的 beforeSave
方法在我调用 $this->EventsMember->saveAll($data);
时被触发,但看起来它实际上不会保存任何东西。
我被困住了。
更新:事实证明,没有创建任何记录,因为加入记录都是使用 0 的事件 ID 和成员 ID 创建的,这违背了我在这两个字段上组合的唯一键(也就是说,没有成员可以参加一个活动两次)。
这是否表明加入模型 saveAll 功能没有按文档说明工作,因为没有创建成员记录(意味着在加入记录中没有要使用的成员 ID),并且现有的事件 ID 不是是否也传递给加入的 EventsMember 记录?
VERDICT:我将控制器更改为在每条记录上循环,并尝试为数组的每个索引使用$this->EventsMember->saveAll($data)
,而不是一次传递整个数组。它有效,但比我的第一个示例(在最顶部)慢得多。请注意,我正在使用事务,因此使用 atomic => false;
选项可能会加快处理速度,同时仍允许我从任何无效记录中恢复。
底线,如果您需要在连接表记录中保存额外的数据,您必须一次处理一个。如果没有,请使用顶部的方法以获得最佳性能。
【问题讨论】:
【参考方案1】:在这种情况下,您可以使用The Join Model。
【讨论】:
这看起来正是我想要的,但它似乎不起作用。我添加了 hasMany 和 belongsTo 关系,并从连接表 ($this->EventsMember->saveAll()) 中触发了 saveAll,但在任何表中都没有创建记录。我在删除和不删除旧的 HABTM 关系的情况下都尝试了这个。如果我从父表 ($this->Member->saveAll()) 触发 saveAll,则将保存成员记录,但不会保存 EventsMember 记录。我会用结果更新我上面的问题。 谢谢,这让我找到了正确的道路。不幸的是,除非我错过了什么,CakePHP 无法批量保存所有连接表记录。以上是关于CakePHP 使用 saveAll:如何使用 HABTM 链接记录保存额外数据?的主要内容,如果未能解决你的问题,请参考以下文章
cakephp:使用 saveAll(),导入的(非表单相关的)关联数据不保存
CakePHP如何在一个saveAll中不知道外键的情况下创建hasMany数据?