存储在 HABTM 关联中的项目的排序顺序 - CakePHP
Posted
技术标签:
【中文标题】存储在 HABTM 关联中的项目的排序顺序 - CakePHP【英文标题】:Storing sort order for items held in an HABTM association - CakePHP 【发布时间】:2009-06-01 18:58:56 【问题描述】:在 ActiveRecord(Cakephp 风格)设置中,我在 Videos 和 Bins 上有一个 HasAndBelongsToMany 关联设置:Bin 可以存储 n 对视频的引用,并且视频可以属于 n 垃圾箱。
我需要能够手动设置和存储视频在特定 Bin 中的显示顺序(以便客户可以在 Bin 中按特定顺序显示他的视频。)我最初的想法是在 Bin 中创建一个字段按需要出现的顺序存储一组视频 ID。这是处理此问题的最有效方法吗?
如果是这样,当我得到 HABTM 查询结果时,对返回的查询重新排序以匹配已排序的 ID 数组的最干净/最有效的方法是什么?
与 Bin 关联的视频以数组形式返回:
[Video] => Array
(
[0] => Array
(
[id] => 49b2de95-0338-48b9-bc88-01ba35664358
...
)
[1] => Array
(
[id] => 49b1ccad-b770-410e-be46-03a035664358
...
)
或者有没有更好的方法可以在不使用 HABTM 关联的情况下实现我想要做的事情?
提前致谢 -
【问题讨论】:
【参考方案1】:当HABTM变得复杂时该怎么办?
默认情况下,当保存 HasAndBelongsToMany 关系时,Cake 会在保存新行之前删除连接表上的所有行。例如,如果您有一个关联了 10 个孩子的俱乐部。然后,您使用 2 个孩子更新 Club。俱乐部只有 2 个孩子,而不是 12 个。
另请注意,如果您想向连接添加更多字段(创建时间或元信息),这可以通过 HABTM 连接表实现,但重要的是要了解您有一个简单的选项。
两个模型之间的HasAndBelongsToMany 实际上是通过hasMany 和belongsTo 关联关联的三个模型的简写。
考虑这个例子:
Child hasAndBelongsToMany Club
查看此问题的另一种方法是添加会员模型
Child hasMany Membership
Membership belongsTo Child,
ClubClub hasMany Membership.
这两个例子几乎完全相同。他们在数据库中使用相同数量和命名的字段以及相同数量的模型。重要的区别在于“加入”模型的名称不同,而且它的行为更可预测。
在您的示例中,您需要一种在不编辑其他用户视频链接的情况下添加和删除的方法,因此标准 habtm 不太适合您。为这个“加入”创建一个类似于上述 Membership 模型的模型。此外,如果您添加了权重字段,您可以使用 ordered behavior(我写的)来为每个 bin 排序每组视频。然后您将使用以下字段
id, bin_id, video_id, weight
并在行为配置中将 bin_id 设置为“foreign_key”。祝你好运
【讨论】:
是的,因此您的方法不是使用内置的 HABTM 关联,而是创建一个连接表来将包含元数据(重量等)的记录与每个视频相关联,从而对查询提供细粒度的控制。所以我可以通过weight
订购“会员”记录以获得正确的顺序。
好吧,我不确定您是否正确地看到它。我的建议是远离 habtm,从而远离 HABTM,只制作属于 Video 和 Bin 的第三个模型,并且是有序的。
不,我认为我们说的是同一件事。新的第三个模型存储 Bin 需要的关于视频的任何元数据,我可以按任何字段对其进行排序。但是对于您之前的观点:我不能在 VideosBins HABTM 连接表中添加一个“订单”字段,然后使用 Set::sort(来自下面的 Herr Lecter)按该附加字段对检索到的数据进行排序吗?
嘿,我的意思是“加入表”,对不起双重habtm。也许你可以,但是, 1. 为什么? 2.蛋糕如何添加和删除“加入”会给你带来麻烦。 3. PHP 排序比让 sql 处理成本要高得多。【参考方案2】:
好吧,我试图解决这个问题,并认为我找到了最简单的解决方案:
保存相关模型的新顺序时,您可以删除现有关系并按所需顺序添加新关系。这意味着创建的 id 按照您的排序顺序运行,您只需按 id 排序即可显示顺序。
public $hasAndBelongsToMany = array(
'Item' => array(
'order' => 'ItemFoldersItem.id ASC, Item.name DESC',
)
);
是不是很简单?
【讨论】:
唯一的问题是第二次排序总是被忽略,因为 ids 当然是唯一的。所以你仍然需要注意不应该按 ids 的默认排序顺序。【参考方案3】:不知道实现您想要的“最有效”的方式,这取决于您的整个应用程序和您想要完成的任务。我只想记住,最简单的解决方案往往是最好的。
不过,我可以为您提供一个对 Video 数组进行排序的提示!这很容易:
$yourData = Set::sort($yourData, '/Video/id', 'asc');
查看Set class 获取更多糖果。 :)
【讨论】:
这并不能真正解决问题,但感谢您的提醒。我已经将 Set 用于其他事情,但没有用它做太多排序(主要是 Set::extract)。我想我也许可以使用 Set::sort 来部分解决问题(参见上面对 A. Morland 的评论)以上是关于存储在 HABTM 关联中的项目的排序顺序 - CakePHP的主要内容,如果未能解决你的问题,请参考以下文章
尝试在保存时保存 CakePHP HABTM 关系中的重复关联
Rails - 仅根据具体情况引入一些 HABTM 关联,以避免不必要的连接