rfc:sort_strict

PHP RFC: SORT_STRICT Flag

Introduction

This RFC proposes SORT_STRICT, a new flag that enables deterministic, type-aware sorting without sacrificing PHP's flexibility with mixed-type arrays.

PHP was famously created as a loosely typed language, prioritizing flexibility and ease of use. However, the introduction of strict types in PHP 7 marked a massive paradigm shift for the language. Over the last decade, the ecosystem has matured significantly; major frameworks like Symfony and Laravel, along with modern coding standards like PER, have effectively pushed strict typing from an optional feature to a de facto standard for professional PHP development.

Despite this evolution, there is no native way to sort or filter arrays without type coercion. The sort() family defaults to SORT_REGULAR (loose equality), while array_unique() defaults to SORT_STRING (string casting), neither of which distinguishes between values of different types. This creates a friction point where modern application logic is strict, but utility functions remain loose. Currently, developers wishing to filter unique values strictly or sort mixed-type arrays deterministically must implement userspace closures using usort or specific loops. This is verbose, slower than internal C implementations, and prone to error.

Proposal

Add a new constant SORT_STRICT that can be passed to the following functions:

  • Value Sorting: sort(), rsort()
  • Associative Value Sorting: asort(), arsort()
  • Key Sorting: ksort(), krsort()
  • Multi-Array Sorting: array_multisort()
  • Uniqueness: array_unique()

Comparison Logic: The "Strict Total Order"

SORT_STRICT implements a two-step comparison:

Step 1: Compare Types

Values are first compared by their type according to this hierarchy:

NULL < Bool < Int < Float < String < Array < Object < Resource

This ordering progresses from simple to complex types, aligning with PHP's internal type representation.

If types differ, the comparison is decided here. No type coercion occurs.

Step 2: Compare Values

If types are identical, standard PHP comparison semantics apply:

Type Comparison Method
NULL Always equal
Bool false < true
Int Numeric comparison
Float Numeric comparison
String Binary comparison (strcmp)
Array Standard array comparison, with SORT_STRICT applied recursively to elements
Object Standard object comparison, with SORT_STRICT applied recursively to properties of same-class objects (enums are compared by identity)
Resource Resource ID comparison

Differences from SORT_REGULAR

SORT_STRICT applies no type coercion at any level:

  1. Different types are ordered by type, never compared by value.
  2. Same-type values are compared directly, without coercion (e.g., strings lexicographically, not numerically).

The following table illustrates common scenarios where SORT_STRICT provides deterministic results versus SORT_REGULAR:

Input Array SORT_REGULAR Result SORT_STRICT Result Reason
[1, “1”] Equal (treats as duplicates) Distinct (Int vs String) Different types are not equal
[“10”, “2”] [“2”, “10”] (Numeric) [“10”, “2”] (Lexicographic) Strings are not cast to ints
[“1e3”, “1000”] Equal (treats as duplicates) [“1000”, “1e3”] (Lexicographic) No numeric string coercion
[null, false] Equal (treats as duplicates) Distinct (Null vs Bool) Different types are not equal

Examples

array_unique(): Preserving Type-Distinct Values

Prevent data loss when filtering arrays containing distinct values that loose comparison treats as duplicates:

$values = [0, "0", null, false, ""];
 
var_dump(array_unique($values, SORT_REGULAR));
// 3 values lost to type coercion
// array(2) {
//   [0]=> int(0)
//   [4]=> string(0) ""
// }
 
var_dump(array_unique($values, SORT_STRICT));
// All 5 values preserved
// array(5) {
//   [0]=> int(0)
//   [1]=> string(1) "0"
//   [2]=> NULL
//   [3]=> bool(false)
//   [4]=> string(0) ""
// }

sort(): Type-Aware Ordering

Sort mixed-type arrays with deterministic, type-based ordering:

$values = ["1", true, 1, null, 1.0];
 
sort($values, SORT_STRICT);
 
var_dump($values);
// Sorted by type hierarchy: NULL < Bool < Int < Float < String
// array(5) {
//   [0]=> NULL
//   [1]=> bool(true)
//   [2]=> int(1)
//   [3]=> float(1.0)
//   [4]=> string(1) "1"
// }

sort(): Order-Independent Value Matching

Compare arrays for identical values regardless of order:

$expected = [1, "1", true];
$actual = [true, 1, "1"];
 
sort($expected, SORT_REGULAR);
sort($actual, SORT_REGULAR);
 
var_dump($expected === $actual);
// bool(false) - result depends on input order
 
sort($expected, SORT_STRICT);
sort($actual, SORT_STRICT);
 
var_dump($expected === $actual);
// bool(true) - consistent type-based ordering

Backward Incompatible Changes

None. This RFC adds a new constant and does not modify existing behavior.

Proposed PHP Version(s)

Next PHP 8.x

RFC Impact

To the Ecosystem

IDEs, static analyzers, and language servers will need to recognize the new SORT_STRICT constant. No breaking changes are expected.

To Existing Extensions

None.

To SAPIs

None.

Open Issues

None currently.

Future Scope

The array_diff() and array_intersect() families currently hardcode string comparison (SORT_STRING) with no way to change the comparison mode. A future RFC could add a flags parameter to these functions, exposing all sort flags including SORT_STRICT:

  • array_diff(array $array, array ...$arrays, int $flags = SORT_STRING)
  • array_intersect(array $array, array ...$arrays, int $flags = SORT_STRING)

This would enable:

// Current behavior (string comparison)
array_diff([1, 2], ["1", "3"]);  // [2] - int 1 matches string "1"
 
// With SORT_STRICT
array_diff([1, 2], ["1", "3"], SORT_STRICT);  // [1, 2] - no matches, different types
 
// With SORT_NUMERIC
array_diff(["10", "2"], [2, 10], SORT_NUMERIC);  // [] - all match numerically

Voting Choices

Primary vote requiring a 2/3 majority:

Add SORT_STRICT flag as described in this RFC?
Real name Yes No
Final result: 0 0
This poll has been closed.

Patches and Tests

WIP

Implementation

TODO: After acceptance.

References

Rejected Features

None yet.

Changelog

  • 2025-11-29: Initial draft
rfc/sort_strict.txt · Last modified: by jmarble