First, thanks Rowan (same to you Kamil), I do appreciate your thoughts on this...
On 9 Nov 2023, at 20:01, Rowan Tommins <rowan.coll...@gmail.com> wrote: > On 09/11/2023 14:58, Craig Francis wrote: >> We might as well make the PHP 9 upgrade as hard as possible, just to force a >> little bit of `strict_types=1` on everyone. > > > Just to be clear, strict_types has nothing to do with this; strict_types=1 enables strict type checking, which adds fatal type errors instead of coercion (all fine, all good); but for everyone not using strict_types=1, there is a fatal type error when NULL is passed to a function argument, while all other type coercions (e.g. string '5' to int) work? > changing it does not allow you to pass nulls to typed parameters, and never > did: https://3v4l.org/atT0B Yep, specifically for user defined function parameters, but NULL coercion works with string concatenation, == comparisons, arithmetics, sprintf, print, echo, array keys? That said, with the original RFC: https://wiki.php.net/rfc/scalar_type_hints_v5 > "The only exception to this is the handling of NULL: in order to be > consistent with our existing type declarations for classes, callables and > arrays, NULL is not accepted by default" I never understood why NULL was considered a complex value like a class/callable/array, when it's more like a simple bool/int/float/string, where NULL can be coerced (and NULL is documented as being coercible in all other contexts, like concatenation). Also... > “it should be possible for existing userland libraries to add scalar type > declarations without breaking compatibility” But that's not the case; if you add types to a legacy projects functions, fatal type errors happen instead of accepting NULL and coercing it as needed (it's why I never bothered adding types to the legacy project I still look after). > Nor has strict_types=0 ever been aligned to the loosest coercion rules used > in other contexts; for instance, an empty string was never an acceptable > input for an integer parameter, even in versions where it was an acceptable > operand for addition: https://3v4l.org/khD32 Fair, but that makes a little bit more sense to me (although I'd assume an empty string would be coerced to 0). > As for your previous example: > > > redirect('/thank-you/?ref=' . urlencode($ref)); > > If $ref isn't set, any of these might be the correct URL: "/thank-you/", > "/thank-you/?ref=", "/thank-you/?ref=default", ... The language can only > guess one of those. NULL has always been coerced to an empty string with urlencode(), it happens in a lot of projects, and everyone seemed to be fine with it? > A similar example I've come across is in manually escaped SQL (yes, I know, > use parameters instead...): > > $sql = "Insert Into blah ( whatever ) Values ( '" . sql_escape($someVar) . "' > )"; > > Nine times out of ten, if the PHP variable is null, you want an SQL null, not > ''; but if the [imaginary] sql_escape function doesn't reject nulls, you may > not notice the bug until you've ended up with garbage in your DB. Fortunately I only have to maintain 1 legacy project, and I've only had to make 29 edits so far, but every single one involved me adding strval(), it's certainly not making the code better, and I know there are still more to find, but I'll have to wait for customers to trip them. Craig