Table of Contents

PHP RFC: clamp

Introduction

clamp checks if a comparable value is within a certain bound. If the value is in range it returns the value, if the value is not in range it returns the nearest bound.

This RFC is a continuation of https://wiki.php.net/rfc/clamp (https://github.com/php/php-src/pull/7191)

Current userland implementations are handled in several ways, some of which use min and max to check the bound, which is slower than what a native function could do (as per tests linked a native function would be even slightly faster than userland implementation using ternary, while providing some extra validation out of the box: NAN handling and verifying min <= max).

clamp is already available in multiple languages with a rather common implementation and prototype, so this RFC aims to brings this feature natively in PHP also.

echo clamp($percentage, min: 0, max: 100);

Proposal

This RFC proposes a new function: clamp

clamp ( mixed $value, mixed $min, mixed $max ) : mixed

clamp takes three arguments, a $value, $min and $max, then checks if $value is within the bounds of $min and $max (both inclusive).

If $value is in the range (between $min and $max), then $value is returned.

Otherwise, the nearest bound is returned, i.e. if $value > $max, it returns $max, if $value < $min, it returns $min.

If the $min value is greater than $max, a ValueError will be thrown, since that constitutes an invalid bound.

If $min or $max is NAN, a ValueError will be thrown.

Examples

clamp(2, min: 1, max: 3) // 2
clamp(0, min: 1, max: 3) // 1
clamp(6, min: 1, max: 3) // 3
clamp(2, 1.3, 3.4) // 2
clamp(2.5, 1, 3) // 2.5
clamp(2.5, 1.3, 3.4) // 2.5
clamp(0, 1.3, 3.4) // 1.3
clamp(M_PI, -INF, INF) // 3.141592653589793
clamp(NAN, 4, 6) // NAN
clamp("a", "c", "g") // "c"
clamp("d", "c", "g") // "d"
clamp(new \DateTimeImmutable('2025-08-01'), new \DateTimeImmutable('2025-08-15'), new \DateTimeImmutable('2025-09-15'))->format('Y-m-d') // 2025-08-15
clamp(new \DateTimeImmutable('2025-08-20'), new \DateTimeImmutable('2025-08-15'), new \DateTimeImmutable('2025-09-15'))->format('Y-m-d') // 2025-08-20
 
clamp(4, 8, 6)
// Throws ValueError: clamp(): Argument #2 ($min) must be smaller than or equal to argument #3 ($max)
 
clamp(4, NAN, 6)
// Throws ValueError: clamp(): Argument #2 ($min) cannot be NAN
 
clamp(4, 6, NAN)
// Throws ValueError: clamp(): Argument #3 ($max) cannot be NAN

Comparison

clamp($value, $min, $max) will be equivalent to ($value < $min) ? $min : ( ($value > $max) ? $max : $value ) or to max($min, min($max, $value)) in its result and also in what it accepts and how it compares those values, following the usual PHP comparison rules.

In particular, be careful of how arrays and objects are compared; this will only fit for some very specific cases.

Like for min() and max(), the documentation of clamp() will warn users about comparing values of different types. The function accepts mixed to follow the “loosely typed language” rules, but clamp() (like min() and max()) is primarily designed to be used with $value, $min, and $max all being of the same type.

Parameters order

Parameters order is as in the sentence “clamp value between min and max”, (as seen in C++, C#, Python, Java, etc.)

It also happens to be found with the order: clamp(min, value, max) like in CSS.

Order value, min, max as been picked as found to be the more common, but users can use named parameters to force a different order:

clamp(min: 0, value: $angle, max: 90)

Backward Incompatible Changes

No backwards incompatible changes with PHP itself.

clamp will no longer be available as a function name, which could break potential userland implementations.

Proposed PHP Version(s)

RFC Impact

Open Issues

To be found

Future Scope

This section should outline areas that you are not planning to work on in the scope of this RFC, but that might be iterated upon in the future by yourself or another contributor.

This helps with long-term planning and ensuring this RFC does not prevent future work.

Proposed Voting Choices

The vote will require 2/3 majority.

Implementation

RFC implementation can be found in the following pull request: https://github.com/php/php-src/pull/19434.

References

Changelog

Main changes between first implementation (https://github.com/php/php-src/pull/7191) and this one (https://github.com/php/php-src/pull/19434) are: