我已经能够使用CakePHP的saveAll方法同时创建'Members'并将它们注册到'Event'(创建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时这些回调存在一些问题,所以我正在寻找有关这里最佳做法的任何提示。
谢谢!
编辑:我接受了亚当的建议并对我的模型进行了以下更改:// Event.php
var $hasMany = array('EventsMember');
// Member.php
var $hasMany = array('EventsMember');
// EventsMember.php
var $belongsTo = array('Event', 'Member');
然后在我的控制器中,我的代码与我的第二个示例几乎完全相同,只是我从saveAll()
模型中调用了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->EventsMember->saveAll($data);
结果是根本没有保存Member
或EventsMember
条记录。我尝试从Member
模型($this->Member->saveAll($data);
)触发保存,这保存了Member
条记录,但未保存加入EventsMember
条记录。
我尝试删除已有的HABTM关联,但没有任何区别。当我调用beforeSave
时,EventsMember
模型的$this->EventsMember->saveAll($data);
方法会被触发,但看起来它实际上不会保存任何内容。
我受到了阻碍。
更新:事实证明没有创建记录,因为加入的记录都是使用事件ID和成员ID为0创建的,这与我在这两个字段组合的唯一密钥相反(即,没有成员可以两次参加活动。)
这是否表明联接模型saveAll功能无法正常工作,因为未创建成员记录(意味着在加入记录中没有要使用的成员ID),并且现有的事件ID不存在传递到加入的EventsMember记录?
VERDICT:我将控制器更改为在每条记录上循环,并为数组的每个索引尝试$this->EventsMember->saveAll($data)
,而不是一次传递整个数组。它工作,但明显慢于我的第一个例子(在最顶端)。请注意,我正在使用交易,因此使用atomic => false;
选项可能会加快速度,同时仍允许我从任何无效记录中恢复。
底线,如果您需要在连接表记录中保存额外数据,则必须一次处理一个。如果没有,请使用顶部的方法以获得最佳性能。