Backend Development 6 min read

Why PHP’s asort/Arr::sort Shows Different Stability Behaviors in PHP 5, 7, and 8

The article investigates why PHP’s array sorting functions appear stable in some versions and unstable in others, analyzing Laravel’s Arr::sort implementation, PHP source code, version‑specific optimizations, and practical test cases that reveal a quick‑sort threshold causing nondeterministic ordering.

php中文网 Courses
php中文网 Courses
php中文网 Courses
Why PHP’s asort/Arr::sort Shows Different Stability Behaviors in PHP 5, 7, and 8

Recently I encountered an issue where a sorted associative array became unordered after processing on the production server, while the same code worked locally.

The code uses Arr::sort($categories, function ($node) { return $node['default']; }, true); which relies on Laravel’s Arr::sort() that ultimately calls PHP’s asort() function.

In PHP, asort() is implemented in arr.c and delegates the actual sorting to zend_hash_sort() :

<code>PHP_FUNCTION(asort)
{
  zval *array;
  zend_long sort_type = PHP_SORT_REGULAR;
  bucket_compare_func_t cmp;
  ZEND_PARSE_PARAMETERS_START(1, 2)
    Z_PARAM_ARRAY_EX(array, 0, 1)
    Z_PARAM_OPTIONAL
    Z_PARAM_LONG(sort_type)
  ZEND_PARSE_PARAMETERS_END();
  cmp = php_get_data_compare_func(sort_type, 0);
  zend_hash_sort(Z_ARRVAL_P(array), cmp, 0);
  RETURN_TRUE;
}
</code>

The zend_hash_sort() function first stores the original element order in the Z_EXTRA field to enable stable sorting when the hash table has no holes. It then calls the low‑level sort() function, which on PHP 7 is linked to std::sort from LLVM’s libc++ . This implementation uses a quick‑sort algorithm for arrays larger than 16 elements, which is not stable.

PHP 5 directly used quick‑sort for all sizes, so the ordering was always unstable. PHP 7 introduced a special case: for arrays with ≤ 16 elements it uses an insertion‑sort‑like algorithm that preserves order, making the sort appear stable for small test cases but unstable for larger ones.

The stable‑sorting RFC was merged in May 2020 for PHP 8.0, where asort() now guarantees stability regardless of array size.

Example test case used to illustrate the behavior:

<code>$count = 10;
$cc = [];
for ($i = 0; $i < $count; $i++) {
    $cc[] = [
        'id' => $i,
        'default' => rand(0, 10),
    ];
}
$cc = Arr::sort($cc, function ($i) {
   return $i['default'];
});
dd($cc);
</code>

Running this on PHP 7 shows stable ordering only when $count is small; larger counts produce nondeterministic ordering, confirming the quick‑sort threshold effect.

In summary, the observed discrepancy between production (PHP 5) and local (PHP 7/8) environments is caused by version‑specific sorting implementations: PHP 5 always used an unstable quick‑sort, PHP 7 uses a hybrid approach that is stable for small arrays, and PHP 8 enforces stable sorting across all sizes.

BackendperformancephpstabilityLaravelarray-sorting
php中文网 Courses
Written by

php中文网 Courses

php中文网's platform for the latest courses and technical articles, helping PHP learners advance quickly.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.