PHP RFC: clamp
- Version: 2
- Date: 2025-08-21
- Author: kylekatarnls, kylekatarnls@gmail.com
- Status: Under Discussion
- Implementation: https://github.com/php/php-src/pull/19434
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.
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:
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)
- next PHP 8.x
RFC Impact
- To SAPIs: Function will be added to all PHP environments.
- To Existing Extensions: None
- To Opcache: None.
- New Constants: No new constants introduced.
- php.ini defaults: No changes to php.ini introduced.
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
- Implementation of similar methods/functions in other languages:
- Implementation PR: https://github.com/php/php-src/issues/7191
- Discussion on the php.internals mailing list: https://news-web.php.net/php.internals/128570
- Announcement thread: https://externals.io/message/115076
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:
int|float
becamemixed
(accept any comparable value) to better match the PHP “loosely typed language” rule- Support string comparison (alphabetically sorted)
- Support
DateTime
NAN
handling was an open issue in the first implementation, this is now handled (ValueError
if passed asmin
ormax
argument, returned as is if passed asvalue
)- New implementation has arity frameless support