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():

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;
}

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:

$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);

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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

stabilityLaravelarray 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

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.