Laravel 5 Collections: Sorting a Collection Based on a Key Value With sortBy

Laravel 5 Collections: Sorting a Collection Based on a Key Value With sortBy

Laravel 5

The sortBy method is useful and versatile way to sort collections by some key, or by some value returned by a $callback. The $callback can either be a function that defines two parameters: $value and $key or the $callback can be the name of some key to sort the collection by. The $options parameter allows developers to modify the sorting behavior and the $descending parameter controls whether or not the sortBy method will sort the collection ascending (false) or descending (true). The sortBy method does not modify the original collection instance, but will return a new instance of Collection with the items sorted.

Signature

public function sortBy(
    $callback,
    $options = SORT_REGULAR,
    $descending = false
);

Example Use

The following collection of imaginary users will be used when demonstrating the features of the sortBy method:

use Illuminate\Support\Collection;

// Create a new collection instance.
$collection = new Collection([
    [
      'name' => 'Sue',
      'age'  => 23,
      'followers' => [
        'Jim',
        'Donna'
      ]
    ],
    [
      'name' => 'Simon',
      'age' => 38,
      'followers' => [
        'Sue'
      ]
    ],
    [
      'name' => 'Jane',
      'age' => 25,
      'followers' => [
        'Link',
        'Dave',
        'Chase'
      ]
    ],
    [
      'name' => 'Dave',
      'age' => 19,
      'followers' => [
        'Dee Dee',
        'Stevie'
      ]
    ]
]);

It is possible to sort the $collection by name like so:

// Sort the users by name:
$sorted = $collection->sortBy('name');

The $sorted variable would now be an instance of Collection and the items would be in the following order:

{language=text}

Dave
Jane
Simon
Sue

To reverse the order, the following could be used:

$sorted = $collection->sort('name', SORT_REGULAR, true);

The $sorted collection would now be in the following order:

Sue
Simon
Jane
Dave

The users can also be sorted by the number of followers they have. To accomplish this, a callback function must be used:

// Sort the users by the number of followers.
$sorted = $collection->sortBy(function($value, $key) {
    return count($value['followers']);
});

The $sorted collection would now be in the following order:

Simon
Sue
Dave
Jane

Of course, it is often desirable to see which users have the most followers. To do this, use the same techniques as before to change the sort order to descending:

// Sort the users by the number of followers.
$sorted = $collection->sortBy(function($value, $key) {
    return count($value['followers']);
}, SORT_REGULAR, true);

sortBy Options

The $options parameter allows developers to change the sorting behavior of the sortBy method. The accepted options are the same options that are defined for PHP's sort function. The following collection instance will be used throughout this section when describing the behavior of the various options:

use Illuminate\Support\Collection;


/**
 * A simple class to represent an animal.
 *
 * Its only purpose to accept the name of the
 * animal and return it when the object
 * instance is cast to a string.
 */
class Animal {

  /**
   * The name of the animal.
   * 
   * @var string
   */
  private $name = '';

  public function __construct($name) {
    $this->name = $name;
  }

  public function __toString() {
    return $this->name;
  }

}

// Create a new collection instance.
$collection = new Collection([
   0 => 'a2.txt',
   1 => 'a1.txt',
   2 => 'a4.txt',
   3 => new Animal('KANGAROO'),
   4 => new Animal('kangaroo'),
   5 => 'a3.txt',
   6 => 6,
   7 => 5,
   8 => new Animal('macaw'),
   9 => 'candice',
  10 => 'bob',
  11 => 'alice',
  12 => new Animal('zebra')
]);

The $collection contains a diverse range of items. It contains strings, integers and a few Animal instances. The keys of each item have also been explicitly set. This will make it easier to keep track of where each item has moved after the collection is sorted.

The following sort flags are available when using the sortBy method:

Flag Description
SORT_REGULAR This is the default sorting flag. It compares each item normally, without changing the type of each item when comparing.
SORT_NUMERIC This flag will cause each item to be treated as a number when doing the comparison.
SORT_STRING This flag will cause each item to be treated as a string when doing the comparison.
SORT_LOCALE_STRING This flag will cause each item to be treated as a string when doing the comparison, but will also take into account PHP's current locale.
SORT_NATURAL This flag compares each item a string, using a "natural ordering" sorting algorithm, similar to the sort method when working with collections.
SORT_FLAG_CASE Can be combined with the SORT_STRING and SORT_NATURAL flags to sort the strings in a case-insensitive way.

Sorting Flag Comparison Table

The following tables will show how the different sorting flags change the sorting of the previously made $collection. Each sorting flag has its own section, which will follow this section. The first table shows the key and its associated value from the original collection, which can be used to locate the original item from the table that follows. The table that follows shows each sorting flag and the sorting order that would result from using that sorting flag. The collection was sorted by using the string representation of the item's value.

Collection Keys and Values:

Key Data Type Value
0 string a2.txt
1 string a1.txt
2 string a4.txt
3 object (Animal) KANGAROO
4 object (Animal) kangaroo
5 string a3.txt
6 integer 6
7 integer 5
8 object (Animal) macaw
9 string candice
10 string bob
11 string alice
12 object (Animal) zebra

Sorting Flag Result Comparison:

| Original Order | 0 1 2 3 4 5 6 7 8 9 10 11 12 | | SORT_REGULAR | 7 6 3 1 0 5 2 11 10 9 4 8 12 | | SORT_NUMERIC | 8 9 10 11 0 5 2 1 3 4 12 7 6 | | SORT_STRING | 7 6 3 1 0 5 2 11 10 9 4 8 12 | | SORT_STRING | SORT_FLAG_CASE | 7 6 1 0 5 2 11 10 9 4 3 8 12 | | SORT_LOCALE_STRING | 7 6 3 1 0 5 2 11 10 9 4 8 12 | | SORT_NATURAL | 7 6 3 1 0 5 2 11 10 9 4 8 12 | | SORT_NATURAL | SORT_FLAG_CASE | 7 6 1 0 5 2 11 10 9 4 3 8 12 |

The SORT_NUMERIC Flag

The SORT_NUMERIC treats each item as a number when doing the comparison. The following code example shows how to use the SORT_NUMERIC flag when sorting the $collection created previously (the callback function will return the string representation of the item):

// Sort the collection using the SORT_NUMERIC flag.
$sorted = $collection->sortBy(function($value, $key) {
  return (string) $value;
}, SORT_NUMERIC);

The following table will use each item's key to represent the new sort order. It will compare the original collection order, the order when using the SORT_REGULAR flag and the order when using the SORT_NUMERIC flag.

SORT_NUMERIC Result Comparison:

|---|---| | Original Order | 0 1 2 3 4 5 6 7 8 9 10 11 12 | | SORT_REGULAR | 7 6 3 1 0 5 2 11 10 9 4 8 12 | | SORT_NUMERIC | 8 9 10 11 0 5 2 1 3 4 12 7 6 |

The SORT_STRING Flag

The SORT_STRING treats each item as a string when doing the comparison. The following code example shows how to use the SORT_STRING flag when sorting the $collection created previously (the callback function will return the string representation of the item):

// Sort the collection using the SORT_STRING flag.
$sorted = $collection->sortBy(function($value, $key) {
  return (string) $value;
}, SORT_STRING);

The following table will use each item's key to represent the new sort order. It will compare the original collection order, the order when using the SORT_REGULAR flag and the order when using the SORT_STRING flag.

SORT_STRING Result Comparison:

|---|---| | Original Order | 0 1 2 3 4 5 6 7 8 9 10 11 12 | | SORT_REGULAR | 7 6 3 1 0 5 2 11 10 9 4 8 12 | | SORT_STRING | 7 6 3 1 0 5 2 11 10 9 4 8 12 |

SORT_STRING and SORT_FLAG_CASE Flags for Case Insensitivity

The SORT_FLAG_CASE flag can be combined with the SORT_STRING flag to treat each item as a string while also ignored the case of each item. The following example shows how to use the SORT_STRING with the SORT_FLAG_CASE flag when sorting the $collection created previously (the callback function will return the string representation of the item):

// Sort the collection using the SORT_STRING and the
// SORT_FLAG_CASE flags.
$sorted = $collection->sortBy(function($value, $key) {
  return (string) $value;
}, SORT_STRING | SORT_FLAG_CASE);

The following table will use each item's key to represent the new sort order. It will compare the original collection order, the order when using the SORT_STRING flag and the order when using the SORT_STRING combined with the SORT_FLAG_CASE flag.

SORT_STRING | SORT_FLAG_CASE Result Comparison:

|---|---| | Original Order | 0 1 2 3 4 5 6 7 8 9 10 11 12 | | SORT_STRING | 7 6 3 1 0 5 2 11 10 9 4 8 12 | | SORT_STRING | SORT_FLAG_CASE | 7 6 1 0 5 2 11 10 9 4 3 8 12 |

The SORT_LOCALE_STRING Flag

The SORT_LOCALE_STRING treats each item as a string, while also taking into account the current locale, when doing the comparison. The following code example shows how to use the SORT_LOCALE_STRING flag when sorting the $collection created previously (the callback function will return the string representation of the item):

// Sort the collection using the SORT_LOCALE_STRING flag.
$sorted = $collection->sortBy(function($value, $key) {
  return (string) $value;
}, SORT_LOCALE_STRING);

The following table will use each item's key to represent the new sort order. It will compare the original collection order, the order when using the SORT_REGULAR flag and the order when using the SORT_LOCALE_STRING flag.

SORT_LOCALE_STRING Result Comparison:

|---|---| | Original Order | 0 1 2 3 4 5 6 7 8 9 10 11 12 | | SORT_REGULAR | 7 6 3 1 0 5 2 11 10 9 4 8 12 | | SORT_LOCALE_STRING | 7 6 3 1 0 5 2 11 10 9 4 8 12 |

The SORT_NATURAL Flag

The SORT_NATURAL treats each item as a string while using a "natural ordering" algorithm to perform the sorting. The following code example shows how to use the SORT_NATURAL flag when sorting the $collection created previously (the callback function will return the string representation of the item):

// Sort the collection using the SORT_NATURAL flag.
$sorted = $collection->sortBy(function($value, $key) {
  return (string) $value;
}, SORT_NATURAL);

The following table will use each item's key to represent the new sort order. It will compare the original collection order, the order when using the SORT_REGULAR flag and the order when using the SORT_NATURAL flag.

SORT_NATURAL Result Comaprison:

|---|---| | Original Order | 0 1 2 3 4 5 6 7 8 9 10 11 12 | | SORT_REGULAR | 7 6 3 1 0 5 2 11 10 9 4 8 12 | | SORT_NATURAL | 7 6 3 1 0 5 2 11 10 9 4 8 12 |

The SORT_NATURAL and SORT_FLAG_CASE Flags for Case Insensitivity

The SORT_FLAG_CASE flag can be combined with the SORT_NATURAL flag to treat each item as a string while also ignored the case of each item. The following example shows how to use the SORT_NATURAL with the SORT_FLAG_CASE flag when sorting the $collection created previously (the callback function will return the string representation of the item):

// Sort the collection using the SORT_NATURAL and the
// SORT_FLAG_CASE flags.
$sorted = $collection->sortBy(function($value, $key) {
  return (string) $value;
}, SORT_NATURAL | SORT_FLAG_CASE);

The following table will use each item's key to represent the new sort order. It will compare the original collection order, the order when using the SORT_NATURAL flag and the order when using the SORT_NATURAL combined with the SORT_FLAG_CASE flag.

SORT_NATURAL | SORT_FLAG_CASE Result Comparison:

|---|---| | Original Order | 0 1 2 3 4 5 6 7 8 9 10 11 12 | | SORT_NATURAL | 7 6 3 1 0 5 2 11 10 9 4 8 12 | | SORT_NATURAL | SORT_FLAG_CASE | 7 6 1 0 5 2 11 10 9 4 3 8 12 |

Using sortBy With Higher Order Messages

In the following example, we will use the sortBy with higher order messages, which allows us to invoke certain collection methods using PHP's property accessors syntax. To start, we will create a new PeripheralDevice class which will simply hold the name of various peripheral devices:

The PeripheralDevice Class:

class PeripheralDevice
{
    public $name = '';

    public function __construct($name)
    {
        $this->name = $name;
    }
}

Using the new PeripheralDevice class, we can create a collection of device names, transform the simple names into objects, and then sort by the device's name using higher order messages:

 $devices = collect([
            'monitor',
            'keyboard',
            'printer',
            'mouse',
            'microphone'
        ])->transform(function ($device) {
           return new PeripheralDevice($device);
        })->sortBy->name;

After the above code has executed, the $devices variable would reference a collection instance containing PeripheralDevice objects that are sorted alphabetically.

Join the Discussion

Leave a comment

  • Israel
    Israel
    March 11, 2019 4:48 PM Reply

    Great post! Thank you!

Subscribe to our newsletter