Sorting Laravel Collection via Array of Id'S

Sorting Laravel Collection via Array of ID's

You can do this:

$order = $list->item_order;
$list->items->sortBy(function($model) use ($order){
return array_search($model->getKey(), $order);
}

Also you could add an attribute accessor to your model which does the same

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

Usage:

foreach ($list->sortedItems as $item) {
// More Code Here
}

If you need this sort of functionality in multiple places I suggest you create your own Collection class:

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

Then, to actually use that class override newCollection() in your model. In this case it would be in the ChecklistItems class:

public function newCollection(array $models = array())
{
return new MyCollection($models);
}

sort a collection according to an array of IDs in Laravel

You probably have not responded because of differences between config('settings.data_grids') And $categories. So edit your code as follows

Please add these three lines to your code:

$catIds = $categories->pluck('cat_id')->toArray(); //get all cat_id
$diff = array_diff($catIds, $grids_arr); // difference array from query
$grids_arr = array_merge($grids_arr , $diff); //merge difference with array

for example:

        $categories = Category::select('*')->get(); //for example
$array = [
[
"pos" => "0",
"col" => "1",
"row" => "1",
"size_x" => "2",
"size_y" => "1",
"cat_id" => 1,
],
[
"pos" => "0",
"col" => "1",
"row" => "2",
"size_x" => "2",
"size_y" => "1",
"cat_id" => 10,
]
];
$grids = collect($array);

if ($grids->isNotEmpty()) {
$grids_arr = $grids->pluck("cat_id")->toArray();
$grids_arr = array_map('intval', $grids_arr);

//Please add these three lines to your code
$catIds = $categories->pluck('cat_id')->toArray();
$diff = array_diff($catIds, $grids_arr);
$grids_arr = array_merge($grids_arr, $diff);
//-----

$sorted = $categories->sortBy(function ($model) use ($grids_arr) {
return array_search($model->cat_id, $grids_arr);
});

return $sorted->values()->all();
}

Laravel Sort Collection By Dynamic ID array

Collections has a sortBy function that takes a custom callback:

$people_collection = People::find($people)
->sortBy(function($person, $key) use($people) {
return array_search($person->id, $people);
});

See the docs.

Laravel Eloquent - Sort Collection by Column by Array's Order

If your status priority is not in numeric order (e.g. 2 > 1 > 3 > 0), you can alternatively pass a callback function to sortBy:

$collection = collect([
['name' => 'A', 'status' => 0],
['name' => 'B', 'status' => 3],
['name' => 'C', 'status' => 0],
['name' => 'D', 'status' => 1],
['name' => 'E', 'status' => 2],
['name' => 'F', 'status' => 1],
['name' => 'G', 'status' => 3],
['name' => 'H', 'status' => 1],
['name' => 'I', 'status' => 2],
['name' => 'J', 'status' => 3],
]);

// define status priority here
$statusPriorities = [2, 1, 3, 0];

$collection->sortBy(function($order) use($statusPriorities){
return array_search($order['status'], $statusPriorities);
})->values()->all();

Output:

[
[
"name" => "I",
"status" => 2,
],
[
"name" => "E",
"status" => 2,
],
[
"name" => "D",
"status" => 1,
],
[
"name" => "F",
"status" => 1,
],
[
"name" => "H",
"status" => 1,
],
[
"name" => "B",
"status" => 3,
],
[
"name" => "G",
"status" => 3,
],
[
"name" => "J",
"status" => 3,
],
[
"name" => "A",
"status" => 0,
],
[
"name" => "C",
"status" => 0,
],
]

Laravel Sort Parent Collection by their relationship values

There is an SQL approach, that would look something like this. Create an subselect, fetch the date you want to use and order by it.

Event::with(['slots' => function ($q) {
$q->orderBy('date');
$q->orderBy('start_time');
}])
->addSelect([
'date' => Comment::selectRaw('MAX(start_date)')
->whereColumn('events.id', 'comments.event_id'),
])->orderBy('date');

Simply use Laravel relation and do the same, not as performance optimized but very straight forward aproeach.

$events = Event::with(['slots' => function ($q) {
$q->orderBy('date');
$q->orderBy('start_time');
}])->active()->get();

$events->sortBy(function ($event) {
return $event->slots()->max('start_date');
});

sort a laravel collection by another array

Get all IDs from your $slideOrderSetting:

$slideOrderArray = json_decode($slideOrderSetting, true);
$slideOrderIDs = collect($slideOrderArray)->pluck('id')->toArray()

About pluck() method

Then get slides:

$slides = DB::table('homepage_slides')
->orderByRaw(DB::raw('FIELD(id, '.implode(', ', $slideOrderIDs).')'))
->paginate(10)

or

$slides = DB::table('homepage_slides')
->whereIn('id', $slideOrderIDs)
->orderByRaw(DB::raw('FIELD(id, '.implode(', ', $slideOrderIDs).')'))
->paginate(10)


Related Topics



Leave a reply



Submit