Den 2022-03-29 kl. 21:44, skrev Rowan Tommins:
Hi all,

If $foo is not defined, statements such as $foo += 1 and $foo .= 'blah' raise "undefined variable" Warnings in PHP 8, and will throw Errors in PHP 9. However, the very similar looking $foo[] = 1 succeeds silently.

This seems odd to me, as "append to string" and "append to array" seem like very similar operations, with most of the same use cases and possible bugs.


From an *implementation* point of view, this is presumably because they are defined as different Op Codes - ASSIGN_OP for .= and ASSIGN_DIM for []=, I believe. But that doesn't explain *why* ASSIGN_DIM behaves this way.

A *historical* explanation might relate to Perl's "autovivification" feature. However, PHP does *not* implement the same rules as Perl: for instance, Perl will create array dimensions just by reading them, which PHP does not; and Perl has a completely different type system, with cases like "a scalar becomes a reference to a hash unless already a reference to a list". Note also that I'm *not* talking about multi-dimensional arrays with missing keys here, only undefined local variables, as were the subject of the recent RFC.

The *observable behaviour* for most operators in PHP is the same:

1) if the variable is undefined, consider the value to be null
2) coerce the value to the appropriate type; if the value is null, this gives the relevant "empty" value, such as '', 0, or []
3) apply the operator

There isn't anything particularly special with $foo[] = 'bar' in this case, except that it's the only operator that doesn't raise a Warning (and planned Error) at step 1. The same goes for all the other uses of the [] syntax I can think of, like $foo['key'] = 'bar', or $ref =& $foo[].


For example, consider the following simple validation code [https://3v4l.org/pP5CU]:

$requiredFields = ['name', 'age', 'hair_colour'];

// Note: $errorString is not initialised
foreach ( $requiredFields as $field ) {
     if ( ! isset($_POST[$field]) ) {
         $errorString .= "Missing required field '$field'. ";
     }
}
echo $errorString;

This gives an "Undefined variable" Notice / Warning / Error, depending on the version. That's reasonable, as failing to initialise $errorString might cause problems if this code is integrated into a loop or larger function later.

However, switch the code from building up a string to building up an array, and the result is identical, but the Notice / Warning / Error goes away [https://3v4l.org/ojZ1O]:

// Note: $errorArray is not initialised
foreach ( $requiredFields as $field ) {
     if ( ! isset($_POST[$field]) ) {
         $errorArray[] = "Missing required field '$field'. ";
     }
}
echo implode('', $errorArray);


Can anyone give a compelling reason why we should keep this inconsistency, or should I raise an RFC to bring it in line with other undefined variable accesses?


I think it deserves an RFC. Then we also capture your excellent explanation above!

Regards //Björn L

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php

Reply via email to