Laravel – sort collection, JSON returns object

Sorting is very common operation in many languages and a lot of data. Of course the best way is to sort on database, because it’s created for such operations, but sometimes I work with smaller parts of data and do that on API server side. Since when I’ve used Laravel, I often use Collections instead of arrays – they methods are very clean, simple and offer a lot of possibilities. I also often sort collections before outputting them as, for example JSON – natural sorting is more than useful in so many cases. But there is one important thing: if you have associative array (or collection) and use sorting, you client will not receive valid array, but object. This short post will show you, how to deal with it.

It’s of course ok: array has to have numeric indexes from 0 to array length – 1. If we have structure with associative indexes, many languages, like JavaScript, will treat it as object, not as array. What about sorting collections on Laravel then? Well, even if you have numeric, standard keys, it will not always return standard array! There is small example, it will work correctly, but with more data, result is not predictable:

$elements = collect();
$elements->push(
    [
        'id' => 1,
        'name' => '01. Test A'
    ]
);
$elements->push(
    [
        'id' => 2,
        'name' => '02. Test B'
    ]
);
(...)

return $elements->sort(
    static function ($a, $b) {
        return strcmp($a['name'], $b['name']);
    }
);

Looks fine, right? Yeah, but try get some data from database, use in that way and return as JSON – whoops, it isn’t array. It may be very problematic, because it your API client may not expect such data, object instead of array (response structure should be strict, described and included in documentation). What can we do with that issue? There are several methods: we can use toArray method and then use array_values, but it isn’t necessary (also, remember: if you return collection in JSON response, it will automatically call toArray method). The best option is to use values method. It will receive new collection with new, numeric key and will be always tread as standard array on client:

return $elements->sort(
    static function ($a, $b) {
        return strcmp($a['name'], $b['name']);
    }
)->values();

What about associative arrays, custom keys? Well, in that situation, you have to return custom data / object instead of array, or just save your key inside each element (probably it’s already here, but all depends on your case). I hope that quick example can help you solve this small, but irritating issue.