Php 通过ID';s
在仍然通过关系进行访问时,是否可以使用单独的ID数组来订购关系集合 设置为Php 通过ID';s,php,laravel,Php,Laravel,在仍然通过关系进行访问时,是否可以使用单独的ID数组来订购关系集合 设置为检查表有许多检查列表项,我以正常方式访问此关系: foreach ($list->items as $item) { // More Code Here } 现在,$item的所需顺序作为属性存在于属性$list->item\u order下的$list上,它只是用户所需顺序中的$itemID的数组,特定于正在迭代的$list 根据$list模型具有的项目顺序数组,是否有一种可行的方法来对附加到$list的
检查表
有许多检查列表项
,我以正常方式访问此关系:
foreach ($list->items as $item) {
// More Code Here
}
现在,$item
的所需顺序作为属性存在于属性$list->item\u order
下的$list
上,它只是用户所需顺序中的$item
ID的数组,特定于正在迭代的$list
根据$list
模型具有的项目顺序
数组,是否有一种可行的方法来对附加到$list
的$items
进行排序
(我不能只将“订单”列添加到“项目”表中,b/c订单会根据特定的“列表”关系进行更改)
谢谢你的帮助 您可以这样做:
$order = $list->item_order;
$list->items->sortBy(function($model) use ($order){
return array_search($model->getKey(), $order);
}
您还可以向模型中添加属性访问器,该访问器也可以执行相同的操作
public function getSortedItemsAttribute()
{
if ( ! is_null($this->item_order)) {
$order = $this->item_order;
$list = $this->items->sortBy(function($model) use ($order){
return array_search($model->getKey(), $order);
});
return $list;
}
return $this->items;
}
用法:
foreach ($list->sortedItems as $item) {
// More Code Here
}
如果您在多个地方需要此类功能,我建议您创建自己的Collection类:
class MyCollection extends Illuminate\Database\Eloquent\Collection {
public function sortByIds(array $ids){
return $this->sortBy(function($model) use ($ids){
return array_search($model->getKey(), $ids);
}
}
}
然后,在模型中实际使用该类重写newCollection()
。在这种情况下,它将位于ChecklistItems
类中:
public function newCollection(array $models = array())
{
return new MyCollection($models);
}
您可以尝试设置一个关系,该关系将按查找的顺序返回结果。您应该仍然能够立即加载关系,并按指定顺序生成结果。这都是假设
item\u order
字段是以逗号分隔的ID字符串列表
public function itemsOrdered()
{
/**
* Adds conditions to the original 'items' relationship. Due to the
* join, we must specify to only select the fields for the related
* table. Then, order by the results of the FIND_IN_SET function.
*/
return $this->items()
->select('checklist_items.*')
->join('checklists', 'checklist_items.checklist_id', '=', 'checklists.id')
->orderByRaw('FIND_IN_SET(checklist_items.id, checklists.item_order)');
}
或者,如果不想硬编码表/字段:
public function itemsOrdered()
{
$orderField = 'item_order';
$relation = $this->items();
$parentTable = $relation->getParent()->getTable();
$related = $relation->getRelated();
$relatedTable = $related->getTable();
return $relation
->select($relatedTable.'.*')
->join($parentTable, $relation->getForeignKey(), '=', $relation->getQualifiedParentKeyName())
->orderByRaw('FIND_IN_SET('.$related->getQualifiedKeyName().', '.$parentTable.'.'.$orderField.')');
}
现在,您可以:
$list = Checklist::with('items', 'itemsOrdered')->first();
var_export($list->item_order);
var_export($list->items->lists('id'));
var_export($list->itemsOrdered->lists('id'));
只是一个警告:这是相当实验性的代码。它看起来可以处理我可用的少量测试数据,但我在生产环境中没有做过类似的事情。此外,这仅在HasMany关系上进行测试。如果你在博客或类似的网站上尝试这段代码,你会遇到问题。我不知道你在laravel会怎么做,但是我知道,在一个直接的mysql查询中,如果您想要按预定义的顺序排序,您可以使用
字段
或在\u集合中查找\u
作为您的顺序的一部分,并且只需按您想要的顺序列出值。或者可以在select(或order)中使用case语句,返回该列的数字和顺序。除非laravel有其他方法,否则我能想到的唯一其他方法就是将项目存储在数组中,然后使用ID数组进行排序以获得所需的顺序。@Matthew Brown$list->item\u order
是有序的项目数组ID???@voodoo417是的,这是正确的。我最终使用了这种方法,效果很好。我不知道sortBy函数也接受闭包。