Re: Passing null to parameter
| From: | Craig Francis | 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