如何使用asc和desc按多个属性对Laravel收藏进行排序?

vmpqdwk3  于 2023-02-05  发布在  其他
关注(0)|答案(5)|浏览(143)

如果我有一个Illuminate\Support\Collection,我如何通过asc和desc对多个属性进行排序?(这是一个简单的假设-根本不需要查询构建技巧。

$collection = User::all(); // not looking for User::orderBy()->get() solutions.  Read the question.
$sorting_insructions = [
    ['column'=>'first_name', 'order'=>'asc'],
    ['column'=>'date_of_birth', 'order'=>'desc'],
];
$collection->sort(function($a,$b) use ($sorting_instructions){
    // something...
});
yfjy0ee7

yfjy0ee71#

我知道这个问题是从一段时间以前,但如果有人偶然发现它,Laravel现在确实提供了这个功能(v8.x在编写时)。
更多细节请参见官方文档。(排序方式部分的第4个代码块示例)https://laravel.com/docs/8.x/collections#method-sortby

来自文档:

  • 如果要按多个属性对集合进行排序,可以将一个排序操作数组传递给sortBy方法。每个排序操作都应该是一个数组,其中包含要按其排序的属性和所需排序的方向:*
$collection = collect([
    ['name' => 'Taylor Otwell', 'age' => 34],
    ['name' => 'Abigail Otwell', 'age' => 30],
    ['name' => 'Taylor Otwell', 'age' => 36],
    ['name' => 'Abigail Otwell', 'age' => 32],
]);

$sorted = $collection->sortBy([
    ['name', 'asc'],
    ['age', 'desc'],
]);

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

/*
    [
        ['name' => 'Abigail Otwell', 'age' => 32],
        ['name' => 'Abigail Otwell', 'age' => 30],
        ['name' => 'Taylor Otwell', 'age' => 36],
        ['name' => 'Taylor Otwell', 'age' => 34],
    ]
*/

应用于问题中的示例:

/*
$sorting_instructions = [
    ['column'=>'first_name', 'order'=>'asc'],
    ['column'=>'date_of_birth', 'order'=>'desc'],
];
*/

$collection = User::all(); 

$sortedCollection = $collection->sortBy([
    ['first_name','asc'],
    ['date_of_birth','desc'],
])
dced5bon

dced5bon2#

不管是谁使用它,只要记住-你需要根据你使用的是对象集合还是关联数组来调整它。应该是一个简单的调整。只要把$a[]/$b[]的东西改为$a-〉和$b-〉

public static function multiPropertySort(Collection $collection, array $sorting_instructions){

        return $collection->sort(function ($a, $b) use ($sorting_instructions){

            //stuff starts here to answer question...

            foreach($sorting_instructions as $sorting_instruction){

                $a[$sorting_instruction['column']] = (isset($a[$sorting_instruction['column']])) ? $a[$sorting_instruction['column']] : '';
                $b[$sorting_instruction['column']] = (isset($b[$sorting_instruction['column']])) ? $b[$sorting_instruction['column']] : '';

                if(empty($sorting_instruction['order']) or strtolower($sorting_instruction['order']) == 'asc'){
                    $x = ($a[$sorting_instruction['column']] <=> $b[$sorting_instruction['column']]);
                }else{
                    $x = ($b[$sorting_instruction['column']] <=> $a[$sorting_instruction['column']]);

                }

                if($x != 0){
                    return $x;
                }

            }

            return 0;

        })->values();
    }
14ifxucb

14ifxucb3#

就像这样简单:

return $this->items->sortBy([
   ['is_hidden', 'asc'],
   ['title', 'asc']
]);

将那些要排序的字段添加为具有字段名和方向的数组。
:)

fdx2calv

fdx2calv4#

如果你使用Eloquent来获取你的集合示例,在你的查询中使用orderBy方法会更好,特别是当列被索引时:

$sorting_insructions = [
    ['column'=>'first_name', 'order'=>'asc'],
    ['column'=>'date_of_birth', 'order'=>'desc'],
];

$collection = App\User::query();

foreach ($sorting_insructions as $value) {

    $collection->orderBy($value['column'], $value['order']);

}

$users = $collection->get();

EDIT由于问题经过编辑,说明sort应该在查询构建器之外使用,我认为从$sorting_insructions开始以相反顺序链接sortBy和sortByDesc会得到相同的结果:

$collection = App\User::all();

$sorting_insructions = [
    ['column'=>'first_name', 'order'=>'asc'],
    ['column'=>'date_of_birth', 'order'=>'desc'],
];

for ($i = count($sorting_insructions) - 1; $i >= 0 ; $i--) { 

    extract($sorting_insructions[i]);

    if ( $order === 'asc') {
        $collection = $collection->sortBy( $column );
    } else {
        $collection = $collection->sortByDesc( $column );
    }

}
zynd9foi

zynd9foi5#

public static function multiPropertySort(
    Collection $collection,
    array $rules
)
{
    return $collection->sort(
        function ($a, $b) use ($rules) {
            foreach($rules as $rule){
                $sortColumn = array_get($rule, 'column');

                array_set(
                    $a,
                    $sortColumn,
                    array_get($a, $sortColumn, '')
                );

                array_set(
                    $b,
                    $sortColumn,
                    array_get($b, $sortColumn, '')
                );

                if ($sortOrder = array_get($rule, 'order', 'asc')) {
                    $x = (array_get($a, $sortColumn) <=> array_get($b, $sortColumn));
                } else {
                    $x = (array_get($b, $sortColumn) <=> array_get($a, $sortColumn));
                }

                if ($x != 0) {
                    return $x;
                }
            }

            return 0;
        }
    );
}

让我们想象一些必要的事情...

相关问题