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



Reply via email to