正如@derekaug 提到的,sort 方法允许我们输入自定义闭包来对集合进行排序。但我认为他的解决方案写起来有点麻烦,如果有这样的东西会很好:
$collection = collect([/* items */])
$sort = ["column1" => "asc", "column2" => "desc"];
$comparer = $makeComparer($sort);
$collection->sort($comparer);
实际上,这可以通过以下$makeComparer 包装器轻松归档以生成比较闭包:
$makeComparer = function($criteria) {
$comparer = function ($first, $second) use ($criteria) {
foreach ($criteria as $key => $orderType) {
// normalize sort direction
$orderType = strtolower($orderType);
if ($first[$key] < $second[$key]) {
return $orderType === "asc" ? -1 : 1;
} else if ($first[$key] > $second[$key]) {
return $orderType === "asc" ? 1 : -1;
}
}
// all elements were equal
return 0;
};
return $comparer;
};
示例
$collection = collect([
["id" => 1, "name" => "Pascal", "age" => "15"],
["id" => 5, "name" => "Mark", "age" => "25"],
["id" => 3, "name" => "Hugo", "age" => "55"],
["id" => 2, "name" => "Angus", "age" => "25"]
]);
$criteria = ["age" => "desc", "id" => "desc"];
$comparer = $makeComparer($criteria);
$sorted = $collection->sort($comparer);
$actual = $sorted->values()->toArray();
/**
* [
* ["id" => 5, "name" => "Hugo", "age" => "55"],
* ["id" => 3, "name" => "Mark", "age" => "25"],
* ["id" => 2, "name" => "Angus", "age" => "25"],
* ["id" => 1, "name" => "Pascal", "age" => "15"],
* ];
*/
$criteria = ["age" => "desc", "id" => "asc"];
$comparer = $makeComparer($criteria);
$sorted = $collection->sort($comparer);
$actual = $sorted->values()->toArray();
/**
* [
* ["id" => 5, "name" => "Hugo", "age" => "55"],
* ["id" => 2, "name" => "Angus", "age" => "25"],
* ["id" => 3, "name" => "Mark", "age" => "25"],
* ["id" => 1, "name" => "Pascal", "age" => "15"],
* ];
*/
$criteria = ["id" => "asc"];
$comparer = $makeComparer($criteria);
$sorted = $collection->sort($comparer);
$actual = $sorted->values()->toArray();
/**
* [
* ["id" => 1, "name" => "Pascal", "age" => "15"],
* ["id" => 2, "name" => "Angus", "age" => "25"],
* ["id" => 3, "name" => "Mark", "age" => "25"],
* ["id" => 5, "name" => "Hugo", "age" => "55"],
* ];
*/
现在,既然我们在这里谈论 Eloquent,那么您很有可能也在使用 Laravel。所以我们甚至可以将 $makeComparer() 闭包绑定到 IOC 并从那里解决它:
// app/Providers/AppServiceProvider.php
// in Laravel 5.1
class AppServiceProvider extends ServiceProvider
{
/**
* ...
*/
/**
* Register any application services.
*
* @return void
*/
public function register()
{
$this->app->bind("collection.multiSort", function ($app, $criteria){
return function ($first, $second) use ($criteria) {
foreach ($criteria as $key => $orderType) {
// normalize sort direction
$orderType = strtolower($orderType);
if ($first[$key] < $second[$key]) {
return $orderType === "asc" ? -1 : 1;
} else if ($first[$key] > $second[$key]) {
return $orderType === "asc" ? 1 : -1;
}
}
// all elements were equal
return 0;
};
});
}
}
现在您可以在任何需要的地方使用它:
$criteria = ["id" => "asc"];
$comparer = $this->app->make("collection.multiSort",$criteria);
$sorted = $collection->sort($comparer);
$actual = $sorted->values()->toArray();