coerce() function

php.internals

Dmitry Derepko

265 days ago
Hello, From time to time I need to write a few lines of code that usually look ridiculous: $var = $input === ‘yes’ ? ‘yes’ : ’no’ $var = $input !== ‘yes’ ? ’no’ : $yes $var = $input > 10 ? 10 : $input $var = max(-10, min($input, 10) and many other variations. In Kotlin, I can use `coerceIn()` extension function with strings / numbers / comparables, which allows me to write such lines more readable. I suggest to add such function to PHP. The examples above may look like the following $var = coerce($input, variants: [“yes”, “no”], default: “yes”); $var = coerce($input, min: 0, max: 10, default: 5); $var = coerce($input, min: 0, max: 10, default: 5); For sure, that could be different functions not to introduce another overloading function. Or range arguments could be replaced with `range(0, 10)` function. This letter is an intent to start discussion of any possible ways of developing this idea. If we agree that the function has enough value to be bundled I’ll create RFC to push the idea further. So what do you think? ---------- Best regards, Dmitrii Derepko. @xepozz

Rowan Tommins [IMSoP]

265 days ago
Hi Dmitry, On 10 December 2025 07:42:27 GMT, Dmitry Derepko <xepozzd@gmail.com> wrote:
>I suggest to add such function to PHP. The examples above may look like the following > >$var = coerce($input, variants: [“yes”, “no”], default: “yes”); >$var = coerce($input, min: 0, max: 10, default: 5); >$var = coerce($input, min: 0, max: 10, default: 5); > >For sure, that could be different functions not to introduce another overloading function. Or range arguments could be replaced with `range(0, 10)` function.
My first thought was that the min/max variant would be covered by the recently-accepted clamp() function: https://wiki.php.net/rfc/clamp_v2 Looking closer, I see that you want to default to a specific value, not the nearest, so it's not quite the same. I think combining both tasks into one function is definitely the wrong approach. PHP doesn't have function overloading, and although you can partially stimulate it with nullable and optional parameters, the whole thing ends up very messy compared to just having separate functions. Using range() to pass in an array would be less efficient than min and max, but maybe good enough for small ranges. Perhaps in future we will have a separate "lazy range" type, which could then be handled as a special case. In general, I don't think it's a function that I'd use often, but it seems a reasonable enough addition to the language. Thanks, Rowan Tommins [IMSoP]

Dmitry Derepko

263 days ago
> On Dec 10, 2025, at 6:00 PM, Rowan Tommins [IMSoP] <imsop.php@rwec.co.uk> wrote: > > Hi Dmitry, > > On 10 December 2025 07:42:27 GMT, Dmitry Derepko <xepozzd@gmail.com> wrote: > >> I suggest to add such function to PHP. The examples above may look like the following >> >> $var = coerce($input, variants: [“yes”, “no”], default: “yes”); >> $var = coerce($input, min: 0, max: 10, default: 5); >> $var = coerce($input, min: 0, max: 10, default: 5); >> >> For sure, that could be different functions not to introduce another overloading function. Or range arguments could be replaced with `range(0, 10)` function. > > My first thought was that the min/max variant would be covered by the recently-accepted clamp() function: https://wiki.php.net/rfc/clamp_v2 Looking closer, I see that you want to default to a specific value, not the nearest, so it's not quite the same. > > I think combining both tasks into one function is definitely the wrong approach. PHP doesn't have function overloading, and although you can partially stimulate it with nullable and optional parameters, the whole thing ends up very messy compared to just having separate functions. > > Using range() to pass in an array would be less efficient than min and max, but maybe good enough for small ranges. Perhaps in future we will have a separate "lazy range" type, which could then be handled as a special case. > > In general, I don't think it's a function that I'd use often, but it seems a reasonable enough addition to the language. > > Thanks, > > Rowan Tommins > [IMSoP]
Thanks for your thoughts. I agree that it’s better to have a few separate functions for different use cases. Regarding the lazy ranges, basically, it’s kind of `iterable`, but with bounds. I think it could be done as the others are: new IntRangeIterator(start: 0, end: 10, inclusive: true) / or as a new function range_iterator / or as a new flag argument in the original range function. So, there are could be a function with: - manual range bounds — strings — ints — enums? - iterator range bounds — IntRangeIterator(start: 0, end: 10, inclusive: true) — CharRangeIterator(start: ‘A', end: ‘D', inclusive: true) — Any other `iterable`, including Generators and regular arrays Actually, looks quite reasonable to re-use iterables. Nice catch, I really like it. ---------- Best regards, Dmitrii Derepko. @xepozz

Hans Henrik Bergan

263 days ago
trivial to make in userland. how about making a composer coerce package first, give it some time, check if it becomes popular, and if it does catch on, reconsider adding it to core?

Dmitry Derepko

262 days ago
> On Dec 12, 2025, at 9:26 PM, Hans Henrik Bergan <divinity76@gmail.com> wrote: > > trivial to make in userland.
Sure, almost everything is trivial to make in userland and re-use as a function.
> how about making a composer coerce package first, > give it some time, check if it becomes popular, > and if it does catch on, reconsider adding it to core?
I don’t think so. There’s no node-js world with left-pad function. People prefer to write plain php instead of re-using external function that’s needed to be downloaded and correctly loaded with autoload. Too much effort to re-use. Moreover, event if a function is quite popular, it doesn’t mean it should be bundled: `dd` / `dump` / `u` / any Laravel global functions that’s users think it’s bundled. I think it’s better to grep the world with structural search and find some cases: - condition($a) ? $a : expr() - if (condition($a)) { $a = expr() } With more or less popular use-cases: - $a == ‘desc’ ? ‘desc’ : ‘asc’ - $a == ’true’ ? ’true' : ‘false’ - $a > 10 ? 10 : ($a < 0 ? 0 : $a) - max(0, min($a, 10) - in_array($key, $values) ? $key : $default - array_key_exist($key, $values) ? $values[$key] : $default - isset($values[$key]) ? $values[$key] : $default - any similar It could be done if I prepare RFC and it will be necessary. Firstly, I’d like to discuss the idea itself. ---------- Best regards, Dmitrii Derepko. @xepozz

Hans Henrik Bergan

263 days ago
On Wed, 10 Dec 2025 at 08:45, Dmitry Derepko <xepozzd@gmail.com> wrote:
> Hello, > > From time to time I need to write a few lines of code that usually look > ridiculous: > > $var = $input === ‘yes’ ? ‘yes’ : ’no’ > $var = $input !== ‘yes’ ? ’no’ : $yes > $var = $input > 10 ? 10 : $input > $var = max(-10, min($input, 10) > > and many other variations. > In Kotlin, I can use `coerceIn()` extension function with strings / > numbers / comparables, which allows me to write such lines more readable. > > I suggest to add such function to PHP. The examples above may look like > the following > > $var = coerce($input, variants: [“yes”, “no”], default: “yes”); > $var = coerce($input, min: 0, max: 10, default: 5); > $var = coerce($input, min: 0, max: 10, default: 5); > >
btw many of these are already covered by filter_var, $var = $input === ‘yes’ ? ‘yes’ : ’no’ $var = $input !== ‘yes’ ? ’no’ : $yes $var = coerce($input, variants: [“yes”, “no”], default: “yes”); $var = coerce($input, min: 0, max: 10, default: 5); is very close to $var = filter_var($input,FILTER_VALIDATE_BOOL); $var = !filter_var($input,FILTER_VALIDATE_BOOL); $var = filter_var($input,FILTER_VALIDATE_BOOL, ['options'=>['default'=>true]]); $var = filter_var($input, FILTER_VALIDATE_INT, ['options'=>['min_range'=>0, 'max_range'=>10, 'default'=>5]]); but if your syntax idea cover stuff like $var = coerce($input, variants: [“yes”, “no”, "maybe"], default: “yes”); then filter_var does not cover it (well, you could get creative with FILTER_VALIDATE_CALLBACK, but that would be crazy, array_search would be better lel) but even so, your proposed syntax is certainly prettier than filter_var.