[PHP-DEV] coerce() function

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

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: PHP: 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]

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: PHP: 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

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?

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.