2

I need help to sort array by couple of logics

[
  {
    "id": 1,
    "status": "pending",
    "date": "2019-08-01"
  },
  {
    "id": 2,
    "status": "delivered",
    "date": "2019-08-01"
  },
  {
    "id": 3,
    "status": "pending",
    "date": "2019-08-03"
  },
  {
    "id": 4,
    "status": "delivered",
    "date": "2019-08-03"
  },
  {
    "id": 5,
    "status": "delivered",
    "date": "2019-08-02"
  }
]

what I want to do is to sort the array to status pending show first, and then sort it by the date descending

I already test to using sortByDesc from laravel collection but the array looks like sorted it by just 1 function

$collection = $collection->sortByDesc('date')->sortByDesc(function ($row, $key) {
      if($row['status'] == 'pending'){
         return 1;
      }else{
         return 0;
      }
});

My expected final result look like this :

[
  {
    "id": 3,
    "status": "pending",
    "date": "2019-08-03"
  },
  {
    "id": 1,
    "status": "pending",
    "date": "2019-08-01"
  },
  {
    "id": 4,
    "status": "delivered",
    "date": "2019-08-03"
  },
  {
    "id": 5,
    "status": "delivered",
    "date": "2019-08-02"
  },
  {
    "id": 2,
    "status": "delivered",
    "date": "2019-08-01"
  }
]
Effendy Salim
  • 33
  • 3
  • 8

3 Answers3

1

Few solutions:

  1. Use a custom callback and return an array source
$products->sortBy(function($product) {
            return [$product->param1, $product->param2];
 });

This will sort a collection by param2 first, and then by param1

  1. Use a custom callback and return a composite property to sort on source
$posts = $posts->sortBy(function($post) {
    return sprintf('%-12s%s', $post->column1, $post->column2);
});
  1. Sort your array by column 1, then split it up by column 2 and then merge it again (untested).
$collection->sortByDesc('date');
$collection->groupBy('status');
$collection->keyBy('status');

EDIT: Also I'm not sure if sortByDesc('date') works with date strings.

PtrTon
  • 3,705
  • 2
  • 14
  • 24
0

Your expected result can be achieved like this.

$sorted = $collection
              ->sortByDesc('date')
              ->sortBy(function ($item) {
                  return 'pending' == $item['status'] ? 0 : 1;
              })
              ->values();
Tharaka Dilshan
  • 4,371
  • 3
  • 14
  • 28
0

To be more precise:

      $collection= $collection->sort(
        function ($a, $b) {
            if(($a->status== $b->status) &&($a->status== 'pending')){
                return ($a->date >= $b->date) ? -1 : 1;
            }elseif($a->status== 'pending' && ($a->status!= $b->status)){
                return 1;
            }else{
                return ($a->date <= $b->date) ? 1 : -1;
            }
        }
    );
    $collection= $collection->sortByDesc('status');