On 24 October 2025 08:07:02 BST, Alexandre Daubois <alex.daubois+php@gmail.com> wrote:
>Hi everyone,
>
>Nicolas Grekas and I would like to propose this new RFC to the
>discussion. This proposes to introduce two new cast operators to the
>language: (?type) and (!type).
>
>Please find the details here:
>https://wiki.php.net/rfc/nullable-not-nullable-cast-operator
Hi both, and thanks for the RFC.
PHP definitely needs a better range of cast operators, and I've been thinking for a while about
what that should look like. My main concern with this proposal is that it picks a few specific
options and uses syntax in a way that's not easy to extend.
What I mean by that is that there are, roughly, three things that a user might want to specify:
1) What *output types* are desired?
2) What *input values* are considered castable?
3) What should happen for *invalid* values?
For (1), our current casts allow base scalar types + array. I can definitely see value in allowing
nullable types there, but also other complex types, e.g. (string|Widget)$foo could be equivalent to
$foo instanceof Widget ? $foo : (string)$foo
For (2) and (3), you could say our current casts accept anything, but you could argue that they
replace invalid values with a fixed "empty" value from the target type.
More importantly, there are a few different things you might *want* to happen:
- throw an exception, because you expect the cast to succeed, and want to abort if it doesn't
- fill with null, or with some default value from the target type, e.g. because you're
*sanitising* untrusted data and want to proceed with the best you can get
- detect that it *would* fail, e.g. because you're *validating* data.
Throwing exceptions is generally a poor choice for validation or sanitisation, because you have to
either make the user fix one mistake at a time, or add a separate try-catch around every check.
The current RFC adds support for nullable types (1), but only if you *also* want a different set of
validation rules (2) *and* a different behaviour if those rules aren't met (3). That's a
*useful* combination, but it's not the *only* useful combination. Using the (?type) syntax for
that combination makes it hard to add other combinations in future.
Rowan Tommins
[IMSoP]