Hi Rowan, > 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.
Thank you for your interest! I get your concerns about the extension of such syntax, but we don't feel that there would be a particular need of extending this syntax. The syntax does not bring something really new: the behavior described in the RFC already exists in PHP — we are just making it available at the cast level with explicit null handling. > 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. I'm sorry, I think I don't get what you mean. It looks really complex for something that we would like to keep straightforward. This RFC doesn't really introduce *new * behavior: these rules already exist in the engine. Casting with these new operators is indeed stricter than existing ones and it _may_ look it introduces brand new rules, but it actually isn't. This strictness comes from implicit casts already done at function calls. — Alexandre Daubois
