存储在 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的主要内容,如果未能解决你的问题,请参考以下文章

HABTM 关联未保存 - cakephp

尝试在保存时保存 CakePHP HABTM 关系中的重复关联

Rails 搜索 HABTM 关系中的关联模型

Rails - 仅根据具体情况引入一些 HABTM 关联,​​以避免不必要的连接

如何将数据写入 CakePHP 中 HABTM 连接表的 HABTM 关联?

CakePHP HABTM 关系保存新的关联