【问题标题】:How do I sort a Laravel Collection by multiple properties with both asc and desc?如何通过 asc 和 desc 的多个属性对 Laravel 集合进行排序?
【发布时间】:2018-04-29 08:52:00
【问题描述】:

如果我有一个 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...
});

【问题讨论】:

    标签: php laravel sorting collections


    【解决方案1】:

    无论谁使用它,请记住 - 您需要根据您使用的是对象集合还是关联数组来调整它。应该是一个简单的调整。只需将 $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();
        }
    

    【讨论】:

    • Array?也许array
    • 另外,最好使用Laravel的safe array_get array_set
    【解决方案2】:

    如果您使用 Eloquent 来获取您的集合实例,最好在查询中使用 orderBy method,尤其是在列被索引的情况下:

    $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();
    

    编辑因为问题被编辑告诉应该在查询构建器之外使用排序,我认为从$sorting_insructions 以相反的顺序链接sortBysortByDesc 会得到相同的结果:

    $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 );
        }
    
    }
    

    【讨论】:

    • 我认为这是一个 mysql 工作来订购返回的数据,如果 Eloquent 已经为我提供了一个解决方案,我为什么要使用你的解决方案?
    • 因为问题的框架只是一个简化的假设 - 我需要对集​​合进行排序。
    • 当我们想要使用 sort 方法时,特别是当我们手动创建集合时 OR 当我们合并 2 个集合结果时,有一种特殊情况,但是您的问题从使用all 方法来生成一个集合,那么如果我可以使用更快的 orderBy,那么使用 sort 的目标是什么。
    • 老兄......现实生活中的实际情况 - 是来自各种数据库的复合对象的集合 - 这里的假设框架只是让它易于阅读。这个问题很明显是关于集合的,而你的解决方案很明显是关于查询构建器的。
    • 您的新解决方案不会排序两次吗?你最终会得到一个按第二条指令排序的集合。
    【解决方案3】:

    我知道这个问题是很久以前提出的,但如果有人偶然发现它,Laravel 现在确实提供了这个功能(在撰写本文时是 v8.x)。

    查看官方文档了解更多详情。 (排序部分中的第四个代码块示例) 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'],
    ])
    
    

    【讨论】:

      【解决方案4】:
      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;
              }
          );
      }
      

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

      【讨论】:

        【解决方案5】:

        就这么简单:

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

        :)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2010-10-06
          • 1970-01-01
          • 2013-02-14
          • 2015-11-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多