Don*_*nic 43 php eloquent laravel-4
我知道在使用查询构建器时,可以使用多列进行排序
...orderBy('column1')->orderBy('column2')
Run Code Online (Sandbox Code Playgroud)
但现在我正在处理一个集合对象.集合有sortBy方法,但我无法弄清楚如何使它适用于多列.直觉上,我最初尝试使用相同的语法orderBy.
sortBy('column1')->sortBy('column2)
Run Code Online (Sandbox Code Playgroud)
但这显然只是按顺序应用排序,最终按列2排序,忽略column1.我试过了
sortBy('column1', 'column2')
Run Code Online (Sandbox Code Playgroud)
但是抛出错误"asort()期望参数2为long,字符串给出".运用
sortBy('column1, column2')
Run Code Online (Sandbox Code Playgroud)
不会抛出错误,但排序看起来很随机,所以我真的不知道实际上是做什么的.我查看了sortBy方法的代码,但不幸的是我很难理解它是如何工作的.
Mar*_*ker 55
sortBy() 采用闭包,允许您提供应该用于排序比较的单个值,但是您可以通过将多个属性连接在一起来使其成为复合
$posts = $posts->sortBy(function($post) {
return sprintf('%-12s%s', $post->column1, $post->column2);
});
Run Code Online (Sandbox Code Playgroud)
如果你需要对多列进行sortBy,你可能需要对它们进行空格键盘以确保"ABC"和"DEF"位于"AB"和"DEF"之后,因此每个列的sprint右边填充到列的长度(至少除了最后一栏以外的所有栏目)
请注意,如果您可以在查询中使用orderBy,那么通常会提高效率,因此在从数据库中检索时,集合已准备就绪
der*_*aug 39
我发现了一种不同的方法来使用sort()雄辩的Collection.它可能比填充字段更好或者至少更容易理解.我有兴趣看看哪个表现更好,因为这个比较多,但我没有sprintf()为每个项目做.
$items->sort(
function ($a, $b) {
// sort by column1 first, then 2, and so on
return strcmp($a->column1, $b->column1)
?: strcmp($a->column2, $b->column2)
?: strcmp($a->column3, $b->column3);
}
);
Run Code Online (Sandbox Code Playgroud)
Hir*_*ter 12
正如@derekaug所提到的,该sort方法允许我们输入自定义闭包来对集合进行排序.但我认为他的解决方案写起来有点麻烦,并且很高兴有这样的东西:
$collection = collect([/* items */])
$sort = ["column1" => "asc", "column2" => "desc"];
$comparer = $makeComparer($sort);
$collection->sort($comparer);
Run Code Online (Sandbox Code Playgroud)
实际上,这可以通过以下$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;
};
Run Code Online (Sandbox Code Playgroud)
例子
$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"],
* ];
*/
Run Code Online (Sandbox Code Playgroud)
现在,既然我们在这里谈论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;
};
});
}
}
Run Code Online (Sandbox Code Playgroud)
现在,您可以在任何需要的地方使用它:
$criteria = ["id" => "asc"];
$comparer = $this->app->make("collection.multiSort",$criteria);
$sorted = $collection->sort($comparer);
$actual = $sorted->values()->toArray();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
24433 次 |
| 最近记录: |