PHPackages                             techworker/php-fn-sortby - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. techworker/php-fn-sortby

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

techworker/php-fn-sortby
========================

Small function that can be used to sort an array of any shape. PHP7 only.

113[1 issues](https://github.com/Techworker/php-fn-sortby/issues)PHP

Since Jul 6Pushed 9y ago1 watchersCompare

[ Source](https://github.com/Techworker/php-fn-sortby)[ Packagist](https://packagist.org/packages/techworker/php-fn-sortby)[ RSS](/packages/techworker-php-fn-sortby/feed)WikiDiscussions master Synced 2mo ago

READMEChangelogDependenciesVersions (1)Used By (0)

php-fn-sortBy
=============

[](#php-fn-sortby)

Prepares a sort function to be used in combination with [usort](https://php.net/) to sort an array of any shape in a functional way.

```
sortBy(..)->thenBy(..)->thenBy(.., \SORT_DESC)
```

[![Minimum PHP Version](https://camo.githubusercontent.com/a61a3990fc7980e135b6d9cf83be9cfe0828864291531176094bc2de0157b0aa/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d372d677265656e2e7376673f7374796c653d666c61742d737175617265)](https://php.net/)

Installation
------------

[](#installation)

You may use [Composer](https://getcomposer.org/) to download and install the function as well as its dependencies.

Simply add a dependency on techworker/php-fn-sortby to your project's composer.json file. Here is a minimal example of a composer.json file that defines a dependency on php-fn-sortby version 1.\*:

```
{
    "require": {
        "techworker/php-fn-sortby": "~1.0"
    }
}
```

Small drawback I think you should know about, but I would say OpCache will work around this:

The library uses composers `autoload->files` to make the function available to you. Autoloading for functions does not work in PHP. So the file is always loaded, no matter if it used or not.

You can, of course, download the lib and require it as you wish.

Definition and usage
--------------------

[](#definition-and-usage)

First import the function so you can easily use or alias it.

```
// import
use function techworker\fn\sortBy;

// usage
sortBy($criteria1)->thenBy($criteria2)->thenBy($criteria3);
```

The only visible function for you is `sortBy`. Everything else are dynamically created functions (or better objects implementing the `techworker\fn\ThenByInterface`) that you can use in the same way as `sortBy`.

The definition looks like this:

`sortBy(int|string|callable $comparator[, int $direction = \SORT_ASC[, callable $decorator = null]]) : ThenByInterface`

- *string | int | callable* **$criteria**This can either be a string or a callable function that returns the value to sort by.
- *int* **$direction**The direction to sort by. This can be one of the two predefined `SORT_*` constants in PHP: [`\SORT_ASC`](http://php.net/manual/en/array.constants.php#constant.sort-asc) AND [`\SORT_DESC`](http://php.net/manual/de/array.constants.php#constant.sort-desc).
- *callable* **$decorator**A decorator that can be used to apply custom sort logic depending on your `$criteria`. The built- in decorator should be powerful enough for 99% of the cases, so just ignoring it will bring you good results. If you ever need another one, go and find out what a decorator does and how to use it. We will omit this in the documentation.

### Using a string as sort criteria

[](#using-a-string-as-sort-criteria)

Imagine we have an array of cities and want to `sortBy` country ascending and `thenBy` population descending.

```
$cities = [
    ['name' => 'Shanghai', 'population' => 24256800, 'country' => 'China'],
    ['name' => 'Karachi',  'population' => 23500000, 'country' => 'Pakistan'],
    ['name' => 'Beijing',  'population' => 21516000, 'country' => 'China']
];
```

This is the most simple use-case and we can do it like this:

```
use function techworker\fn\sortBy;

// create a sort callback used for the builtin PHP usort function.
$sorter = sortBy('name')->thenBy('population', \SORT_DESC);
usort($cities, $sorter);
```

The cities array is now sorted. You can even use an array of objects. The lib will try to determine the value either by an array key `[$criteria]`or by an object property `->{$criteria}`.

### Using a callback as sort criteria

[](#using-a-callback-as-sort-criteria)

If you need some deeper login to retrieve a sort criterial, you can provide a function.

Imagine you have an array of departments with its employees and an avg salary nested like this:

```
$departments = [
    'devops' => [
        'employees' => ['ben', 'peter', 'james', 'lisa', 'tequila'], // 5
        'salary' => 4000
    ],
    'sysop' => [
        'employees' => ['titus', 'raffy', 'ramanda', 'kathleen', 'rufus'], // 5
        'salary' => 3000
    ],
    'mgmt' => [
        'employees' => ['zoey', 'tiny', 'raphael', 'christian', 'michael', 'rene', 'benny',
                        'johannes', 'sebastian', 'pedro', 'christoph'], // 11
        'salary' => 10000
    }
];
```

Now you want to sort this array by the number of employees DESC and then by the salary DESC. The expected result should be something like this:

- mgmt -&gt; 11 employees, 10000 salary
- devop -&gt; 5 employees, 4000 salary
- sysop -&gt; 5 employees, 3000 salary

Here is how it can work:

```
use function techworker\fn\sortBy;

// I declare the callback in variables for better readability
$fnNumberEmployees = function($department) {
    return count($department['employees']);
}

// create a sort callback used for the builtin PHP usort function.
$sorter = sortBy($fnNumberEmployees, \SORT_DESC)->thenBy('salary', \SORT_DESC);
usort($departments, $sorter);
```

As you might know, a comparer function provided to `usort` is expecting 2 parameters and returns an integer to tell the sorter if the value is `bigger` (&gt;0), `lower` (&lt;0) or `equal` (0).

The wrapping of your callback with just one parameter is done by the decorator (3. parameter of the inital `sortBy` call).

So if you provide a callback with only one parameter (unary), the decorator will automatically wrap the function and will do the comparism for you using the spaceship operator ``.

If you provide a callback with two parameters, you can do the comparism by yourself.

See the following example for a callback that uses 2 parameters:

```
use function techworker\fn\sortBy;

// I declare the callback in variables for better readability
$fnNumberEmployees = function($department1, $department2) {
    return count($department1['employees']) - count($department2['employees']);
    // or
    // return count($department1['employees'])  count($department2['employees']);
}

// create a sort callback used for the builtin PHP usort function.
$sorter = sortBy($fnNumberEmployees, \SORT_DESC)->thenBy('salary', \SORT_DESC);
usort($departments, $sorter);
```

This should give you the same results as above, but you gain more control about the comparing functionality itself.

### ThenByInterface

[](#thenbyinterface)

The `sortBy` and `thenBy` function all return a dynamic class instance of the `ThenByInterface`, so it is easier for the IDE to autocomplete the calls.

Take a look at the implementation src, it's fairly simple compared to various other solutions. It just looks complicated. If you have any bugs, suggestions, whatever, get in touch with me through the GitHub issues.

I hope you find this useful!

Credits
-------

[](#credits)

This function is roughly ported from  - a javascript function with more or less the same set of features. Thanks a lot for the idea!

The kicker to port and enhance it was the following issue:

[Teun/thenBy.js#10](https://github.com/Teun/thenBy.js/issues/10) :-)

###  Health Score

15

—

LowBetter than 3% of packages

Maintenance0

Infrequent updates — may be unmaintained

Popularity7

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity41

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/56e0f4be9fdda71be24a095e3740a862e5d0870e3dbef4d298b0d9b04ef47abd?d=identicon)[BenjaminAnsbach](/maintainers/BenjaminAnsbach)

---

Top Contributors

[![Techworker](https://avatars.githubusercontent.com/u/789017?v=4)](https://github.com/Techworker "Techworker (13 commits)")

### Embed Badge

![Health badge](/badges/techworker-php-fn-sortby/health.svg)

```
[![Health](https://phpackages.com/badges/techworker-php-fn-sortby/health.svg)](https://phpackages.com/packages/techworker-php-fn-sortby)
```

###  Alternatives

[arokettu/phpstorm-metadata-export

Export PhpStorm Advanced Metadata from DI containers

1234.0k1](/packages/arokettu-phpstorm-metadata-export)[seferov/composer-env-script

Composer script for handling gitignored env files

1139.0k](/packages/seferov-composer-env-script)[verbb/single-cat

A field type to allow users to select a single category from a dropdown.

114.2k](/packages/verbb-single-cat)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
