What is the syntax for sorting an Eloquent collection by multiple columns?
sortBy()
takes a closure, allowing you to provide a single value that should be used for sorting comparisons, but you can make it a composite by concatenating several properties together
$posts = $posts->sortBy(function($post) {
return sprintf('%-12s%s', $post->column1, $post->column2);
});
If you need the sortBy against multiple columns, you probably need to space pad them to ensure that "ABC" and "DEF" comes after "AB" and "DEF", hence the sprint right padded for each column up to the column's length (at least for all but the last column)
Note that it's generally a lot more efficient if you can use an orderBy in your query so the collection is ready-sorted on retrieval from the database
Sorting collection 2 times
Create a multi dimension array, with points being the the first key and victory being the second key, php will automatically sort them key wise.
<?php
//each array with (Teams, Points, Wins)
$rank[] = array('Team' => "A", 'Points' => 24, 'Wins' => 11);
$rank[] = array('Team' => "B", 'Points' => 26, 'Wins' => 11);
$rank[] = array('Team' => "C", 'Points' => 25, 'Wins' => 10);
$rank[] = array('Team' => "D", 'Points' => 24, 'Wins' => 12);
$rank[] = array('Team' => "E", 'Points' => 25, 'Wins' => 11);
$rank[] = array('Team' => "F", 'Points' => 27, 'Wins' => 13);
foreach ($rank as $key => $row) {
$points[$key] = $row['Points'];
$wins[$key] = $row['Wins'];
}
array_multisort($points, SORT_DESC, $wins, SORT_DESC, $rank);
echo "<ol>";
for ($line = 0; $line < 6; $line++){
echo "<li><b> Rank</b>";
foreach($rank[$line] as $key => $value){
echo "|".$key."-".$value."|";
}
echo "</li>";
}
echo "</ol>";
?>
laravel - how to sort by different columns (first integer and then string)
Use ORDER BY sort_order, title
, its equivalent in Laravel being:
$parts = \App\DevicePart::with('device')
->orderBy('sort_order')
->orderBy('title')
->get();
How can i sort an laravel eloquent query by one-to-many relation
I solved this problem:
First off all add a hasOne relation to Product model:
public function latestInventory()
{
return $this->hasOne(Inventory::class);
}
Then in ProductController:
$products = Product::with(['latestInventory' => function($query) {
$query->where('count', '>', 0)->orderBy('id');
}]);
$products = $products->get();
$products = $products->sortBy('latestInventory.price')->paginate(16);
return $products->values()->toArray();
For Paginate the collection :
In ASP (AppServiceProvider.php) on boot method:
Collection::macro('paginate', function($perPage, $total = null, $page = null, $pageName = 'page') {
$page = $page ?: LengthAwarePaginator::resolveCurrentPage($pageName);
return new LengthAwarePaginator(
$this->forPage($page, $perPage),
$total ?: $this->count(),
$perPage,
$page,
[
'path' => LengthAwarePaginator::resolveCurrentPath(),
'pageName' => $pageName,
]
);
});
In app/Support/Collection.php:
<?php
namespace App\Support;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection as BaseCollection;
class Collection extends BaseCollection
{
public function paginate($perPage, $total = null, $page = null, $pageName = 'page')
{
$page = $page ?: LengthAwarePaginator::resolveCurrentPage($pageName);
return new LengthAwarePaginator(
$this->forPage($page, $perPage),
$total ?: $this->count(),
$perPage,
$page,
[
'path' => LengthAwarePaginator::resolveCurrentPath(),
'pageName' => $pageName,
]
);
}
}
Laravel - Sort array by string value first and then date
Few solutions:
- Use a custom callback and return an array source
$products->sortBy(function($product) {
return [$product->param1, $product->param2];
});
This will sort a collection by param2 first, and then by param1
- Use a custom callback and return a composite property to sort on source
$posts = $posts->sortBy(function($post) {
return sprintf('%-12s%s', $post->column1, $post->column2);
});
- Sort your array by column 1, then split it up by column 2 and then merge it again (untested).
$collection->sortByDesc('date');
$collection->groupBy('status');
$collection->keyBy('status');
EDIT: Also I'm not sure if sortByDesc('date')
works with date strings.
Laravel - sorting an array of collections by the property of their relationship object
First of all: Instead of using Collection::groupBy()
you can just use relations:
$magazines = Magazine::with(['issues' => function($query) {
$query->orderBy('date', 'desc');
}]);
This will give you a collection of Magazines including related issues in an array. The issues
array is sorted by date desc
.
Now you can split the result using two queries with different conditions:
$baseQuery = Magazine::with(['issues' => function($query) {
$query->orderBy('date', 'desc');
}]);
$query1 = clone $baseQuery;
$query2 = clone $baseQuery;
$query1->whereIn('product_code', $productCodes);
$query2->whereNotIn('product_code', $productCodes);
$query1
will return all magazines with product_code
from the array. $query2
will return all the other magazines.
You have now two ways to combine the two results:
1) Use Eloquent::unionAll()
$unionQuery = $query1->unionAll($query2);
$magazines = $unionQuery->get();
2) Use Collection::merge()
$magazines1 = $query1->get();
$magazines2 = $query2->get();
$magazines = $magazines1->merge($magazines2);
In both cases you will get the same result: A collection of magazines. The magazines with product_code
from the $productCodes
array are sorted first. Every Magazine
object contains an array issues
with related Issue
objects.
If you want to get rid of the Magazine
objects and really need the result to look like in your question, you can still do:
$issues = $magazines->keyBy('id')->pluck('issue');
But there is probably no need for that.
Update
If you really need the two parts of the Magazine
collection to be sorted by the latest Issue
.. I don't see any way without using a JOIN or sorting in PHP with a closure. Sorting magazines with a join would also need an aggregation. So i would switch back to your original query extending it with a join and split it in two parts as showed above:
$baseQuery = Issue::join('magazines', 'magazines.id', '=', 'issues.magazine_id');
$baseQuery->orderBy('issues.date', 'desc');
$baseQuery->select('issues.*');
$query1 = clone $baseQuery;
$query2 = clone $baseQuery;
$query1->whereIn('magazines.product_code', $productCodes);
$query2->whereNotIn('magazines.product_code', $productCodes);
And then
$issues1 = $query1->get()->groupBy('magazine_id');
$issues2 = $query2->get()->groupBy('magazine_id');
$issues = $issues1->union($issues2);
or
$issues = $query1->unionAll($query2)->get()->groupBy('optionGroupId');
Laravel Eloquent: How to order results of related models?
You have a few ways of achieving this:
// when eager loading
$school = School::with(['students' => function ($q) {
$q->orderBy('whateverField', 'asc/desc');
}])->find($schoolId);
// when lazy loading
$school = School::find($schoolId);
$school->load(['students' => function ($q) {
$q->orderBy('whateverField', 'asc/desc');
}]);
// or on the collection
$school = School::find($schoolId);
// asc
$school->students->sortBy('whateverProperty');
// desc
$school->students->sortByDesc('whateverProperty');
// or querying students directly
$students = Student::whereHas('school', function ($q) use ($schoolId) {
$q->where('id', $schoolId);
})->orderBy('whateverField')->get();
Related Topics
Issues with PHP 5.3 and Sessions Folder
Fatal Error - 'Mongo' Class Not Found
Sort Array in PHP by Value and Maintain Index Association
When Do I Use Static Variables/Functions in PHP
Codeigniter: Best Way to Structure Partial Views
Resetting MySQL Root Password with Xampp on Localhost
Doctrine - How to Print Out the Real SQL, Not Just the Prepared Statement
How to Solve Error 404 When Deploying Laravel Project to Cpanel
PHP Password_Verify() Hash and Pass Won't Match
How to Escape Single-Quote (Apostrophe) in String Using PHP
How to Include External CSS and Js File in Laravel 5
What Is Normalized Utf-8 All About