Reputation: 1302
I have quite complex laravel eloquent collection which need to be sorted by projectid,date, username.
I have been searching google but no one had asked or wrote about this complex sort.
If I only use desc or asc order with sortBy function. It works but if i try to use desc/asc both it mix up..
How can I solve this problem???
collection structure
collection {
array (size=148)
0 =>
attribute:
id:100,
date:"2015-02-03"
relations:
0 project(belongstomany relationship)
projectid: 1
1 user(belongstomany relationship)
username:"test"
}
This should be sorted like this
project id(desc) date(desc) name(asc)
9 2015-02-31 test1
9 2015-02-30 test2
8 2015-02-30 test2
7 2015-02-29 test3
6 2015-02-28 test4
5 2015-02-27 test5
Upvotes: 0
Views: 1341
Reputation: 62228
You can do what you want, but you have to use the sort()
method, not the sortBy()
method. The sort()
method will take a closure that you can use to define your custom sort algorithm. Basically, if you pass a closure to sort()
, it will call PHP's usort()
with your closure to sort the items.
This is just a rough idea of what you're looking for. You will probably have to tweak it since there are few uncertainties from what you've posted. You can define this as an actual function to pass into sort()
, or you can just pass it into sort()
as an anonymous function.
function ($a, $b) {
/**
* Your question states that project is a belongsToMany relationship.
* This means that project is a Collection that may contain many project
* objects, and you need to figure out how you want to handle that. In
* this case, I just take the max projectid from the Collection (max,
* since this field will be sorted desc).
*
* If this is really just a belongsTo, you can simplify this down to
* just $a->project->projectid, etc.
*/
$aFirst = $a->project->max('projectid');
$bFirst = $b->project->max('projectid');
/**
* If the projectids are equal, we have to dig down to our next comparison.
*/
if ($aFirst == $bFirst) {
/**
* Since the first sort field (projectids) is equal, we have to check
* the second sort field.
*/
/**
* If the dates are equal, we have to dig down to our next comparison.
*/
if ($a->date == $b->date) {
/**
* Your question states that user is a belongsToMany relationship.
* This means that user is a Collection that may contain many user
* objects, and you need to figure out how you want to handle that.
* In this case, I just take the min username from the Collection
* (min, since this field will be sorted asc).
*/
$aThird = $a->user->min('username');
$bThird = $b->user->min('username');
/**
* If the final sort criteria is equal, return 0 to tell usort
* that these two array items are equal (for sorting purposes).
*/
if ($aThird == $bThird) {
return 0;
}
/**
* To sort in ascending order, return -1 when the first item
* is less than the second item.
*/
return ($aThird < $bThird) ? -1 : 1;
}
/**
* To sort in descending order, return +1 when the first item is
* less than the second item.
*/
return ($a->date < $b->date) ? 1 : -1;
}
/**
* To sort in descending order, return +1 when the first item is
* less than the second item.
*/
return ($aFirst < $bFirst) ? 1 : -1;
}
For more information on how usort()
works, you can check the docs.
Upvotes: 1