CakePHP使用saveAll:如何使用HABTM链接记录保存额外数据?

时间:2011-02-26 21:44:30

标签: cakephp transactions

我已经能够使用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);

结果是根本没有保存MemberEventsMember条记录。我尝试从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;选项可能会加快速度,同时仍允许我从任何无效记录中恢复。

底线,如果您需要在连接表记录中保存额外数据,则必须一次处理一个。如果没有,请使用顶部的方法以获得最佳性能。

1 个答案:

答案 0 :(得分:1)

在这种情况下,您可以使用The Join Model