Re: Passing null to parameter

From: Date: Fri, 10 Nov 2023 11:29:46 +0000
Subject: Re: Passing null to parameter
References: 1 2 3  Groups: php.internals 
Request: Send a blank email to internals+get-121634@lists.php.net to get a copy of this message
First, thanks Rowan (same to you Kamil), I do appreciate your thoughts on this... On 9 Nov 2023, at 20:01, Rowan Tommins <rowan.collins@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

« previous php.internals (#121634) next »