PHP 8.6 Replaces Two Old Habits: clamp() and the SortDirection Enum
Scott Keck-Warren • November 13, 2026
I would like to show you two pieces of code I think I've seen in every codebase I've worked on:
$percent = -5;
if ($percent < 0) {
$percent = 0;
}
if ($percent > 100) {
$percent = 100;
}
and
// what does 1 mean here?
sortResults($rows, 1)
Both are small, so they don't get refactored, but that doesn't mean they're not hiding bugs (especially that Magic number, yuck). PHP 8.6 (out November 19, 2026) is going to give us standard replacements to make all of our lives easier.
clamp(): Keep a Value in Range
The clamp() function is going to allow us to take our first example and convert it into a one-liner.
$percent = clamp($percent, 0, 100);
Or better yet, limit what our untrustworthy users are trying to do:
$page = clamp((int) ($_GET['page'] ?? 1), 1, $totalPages);
clamp() Edge Cases
There are a couple of interesting edge cases that clamp() makes impossible to mess up.
First, if you swap min and max, you'll get an error.
// Warning: Uncaught ValueError: clamp(): Argument #2 ($min) must be smaller than or equal to argument #3 ($max)
$percent = clamp(-5, 100, 0);
This is important if you have pagination and the total pages are zero because this will also error out.
$currentPage = clamp($page, 1, $totalPages);
So we'll still have to check it:
$currentPage = 0;
if ($totalPages >= 1) {
$currentPage = clamp($page, 1, $totalPages);
}
It's also set to accept a mixed type so you can do crazy things like run floats, strings, and DateTimeImmutable objects through it based on PHP's existing comparison rules (which might trigger Type Juggling).
// float(1)
var_dump(clamp(1.1, 0, 1.0));
// string(1) "c"
var_dump(clamp('a', 'c', 'g'));
// DateTimeImmutable("2026-01-01 00:00:00.000000")
var_dump(clamp(new DateTimeImmutable("2020-01-01"), new DateTimeImmutable("2026-01-01"), new DateTimeImmutable()));
Using clamp() Before 8.6
So if you're stuck on a release before 8.6 but want to take advantage of clamp() now you can use https://github.com/symfony/polyfill-php86 to make it available to you (thanks, Symfony Team) even in a PHP 8.1 codebase (please upgrade).
The SortDirection Enum
One of my favorite features added in the PHP 8.x line is native support for Enums. Enums provide a way for us to say only a fixed set of "constant" values are allowed, which makes our code more readable and less error-prone.
Our example above uses sortResults(), which will take ANY integer value and may type-juggle something like a string to the integer (weirder things have happened).
// an integer is a fragile way to sort
function sortResults(array $rows, int $direction): array
{
// logic
}
PHP 8.6 is adding a global enum for sort direction.
enum SortDirection
{
case Ascending;
case Descending;
}
From the sound of it this is going to be rolled out to sort functions that currently take a constant but we can start using it for our code now.
// Now we only have two options
function sortResults(array $rows, SortDirection $direction): array
{
// logic
}
Why It's Unbacked
PHP's enum support allows us to set a "backing" value (string or int), but the SortDirection has no "correct" backing value ('asc', 'ASC', SORT_ASC, 1?). The RFC left this up to the individuals to do, but it's easy enough to do.
$sql = match ($direction) {
SortDirection::Ascending => 'ASC',
SortDirection::Descending => 'DESC',
};
What SortDirection Won't Do Yet
SortDirection doesn't currently support any of the built-in functions. Functions like sort(), array_multisort(), and scandir() are still accepting ints. I'm guessing we'll see a rash of RFCs to roll this out over the coming releases.
The value is using it in your own code (and hopefully your Framework's code). You can swap out your userland 'asc'|'desc' strings and homegrown Direction enums SortDirection so packages share a type. Then PHPStan or Psalm will catch typos, which they can't do with a string or int.
What You Need to Know
PHP 8.6 is adding two small features that clarify ideas we all have but might not be reflected in the codebase. We can use them NOW using https://github.com/symfony/polyfill-php86.
Both features are in my PHP 8.6 roundup. You can watch the video at https://www.youtube.com/watch?v=U9Jrcg1Ns1k, or read the written version at https://www.phparch.com/2026/09/stop-writing-php-like-this-8-6-fixes-it/ . Next week we're going to cover the session default changes and deprecations, so make sure you subscribe.
AI notice:
The outline for this post was generated via AI, then I wrote the prose and ran it through Grammarly