laravel - 已解决:寻找一种更智能的方式来同步和排序 Laravel/Eloquent 数据透视表中的条目
问题描述
在我的 Laravel 5.1 应用程序中,我有 Page(为网页建模)和 Media(为图像建模)类。Page 包含媒体对象的集合,并且这种关系在“media_page”数据透视表中维护。数据透视表包含 page_id、media_id 和 sort_order 列。
网站上的实用程序表单允许管理员手动将一个或多个媒体项与页面相关联,并指定媒体项在视图中呈现的顺序。当表单提交时,控制器会收到一个排序的媒体 ID 列表。关联保存在 Controller 的 store() 和 update() 方法中,如下所示:
[店铺] $page->media()->attach($mediaIds);
[更新]$page->media()->sync($mediaIds);
这工作正常,但不允许我保存在 mediaIds 请求参数中指定的 sort_order。因此,媒体项目总是按照它们在数据库中出现的顺序返回到视图中,而不管管理员如何手动订购它们。我知道在保存单个记录时如何为数据透视表附加额外的数据,但在将数组传递给 attach() 或 sync() 时不知道如何执行此操作(或者是否可能),如上所示。
我能看到的唯一方法是:
遍历数组,为每个条目调用一次 attach() 并将当前计数器索引作为 sort_order 传递。
首先 detach() 所有关联,然后将 mediaIds 数组传递给 attach() 或 sync()。一个附带的好处是它完全不需要 sort_order 列。
我希望有一个更简单的解决方案,需要更少的数据库访问。还是我只是想多了,实际上,自己做循环与让 Laravel 在接收到数组时更进一步做循环没有什么不同?
[解决方案] 我通过如下重塑数组来使其工作。它分解以逗号分隔的 'mediaIds' 请求参数并遍历结果数组,将每个媒体 id 分配为 $mediaIds 数组中的键,将 sort_order 值设置为等于键在数组中的位置。
$rawMediaIds = explode(',', request('mediaIds'));
foreach($rawMediaIds as $mediaId) {
$mediaIds[$mediaId] = ['sort_order' => array_search($mediaId, $rawMediaIds)];
}
然后在检索 Page 的关联媒体时按 sort_order 排序:
public function media() {
return $this->belongsToMany(Media::class)->orderBy('sort_order', 'asc');
}
解决方案
您可以在附加或同步时将数据添加到数据透视表,如下所示:
$mediaIds = [
1 => ['sort_order' => 'order_for_1'],
3 => ['sort_order' => 'order_for_3']
];
//[STORE]
$page->media()->attach($mediaIds;
//[UPDATE]
$page->media()->sync($mediaIds);
推荐阅读
- python - 如何在python列中使用多索引访问数据
- excel - 如何从一个excel表中获取数据并将其添加到不同表中的匹配行?
- c# - 假脱机由 Observable.FromEvent 生成的正在进行的项目
- r - 用R计算多个多边形之间的最小距离
- javascript - Internet Explorer 中的 Angular 无效日期错误
- python - 如何在 Python 中以异步方法上传到 Google Drive
- javascript - 如何创建一个带有反应的小部件以集成到其他反应应用程序中?
- java - 用作常量的 Java final 类在编译后保留
- batch-file - CMD 随时按键触发X
- html - Angular HTML元素:观察自身内部的元素属性