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);

结果是根本没有保存MemberEventsMember 记录。我尝试从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 使用 3 个带有 saveAll 的模型

CakePHP:用户数据 saveAll 静默失败?

CakePHP如何在一个saveAll中不知道外键的情况下创建hasMany数据?

是否可以使用 Cakephp 中的 saveAll 一次将所有相关记录插入到 HABTM 中?

在 CakePHP 中使用 saveAll() 保存多个 hasMany 数据,而无需在视图中写入 id