Hi All,
I would like to propose that the error given for an undefined constant
should be raised from E_NOTICE, probably to E_RECOVERABLE_ERROR, in PHP 7.
I'm happy to expand this into a proper RFC, and work on patches for the
engine, tests, and spec, but want to see if initial reception to the
idea is favourable first.
Current behaviour: any bare word which is not a defined constant is
treated as though it were a quoted string, with an E_NOTICE issued.
Proposed behaviour: an E_RECOVERABLE_ERROR is issued; if the error is
caught, either the existing string behaviour could be retained, or the
value could be treated as NULL. (I'm open to other alternatives.)
PROS
1. Consistency.
An undefined class constant (e.g. Foo::BAR) gives a fatal error, but a
normal global constant gives only a notice. Class constants being "more
modern" made this seem reasonable, but with namespaces, it's even worse
- a qualified namespace constant (e.g. Foo\BAR) gives a fatal error, as
does a global constant in namespace notation (e.g. \BAR); but a
namespace constant referenced relative to the current namespace is a
bare word, and gives only a notice (e.g. namespace Foo; const BAR=42;
echo BAAR;).
Functions and classes also give fatal errors if used without declaring;
variables do not, but this is more useful, because they can meaningfully
be created as null, and there isn't a syntax to declare a local
variable, only to initialise it.
2. Inherent severity.
It's probably relatively common to turn off E_NOTICE in error_reporting,
or to miss one notice among many others. But an undefined constant
magically turning into a string could cause relatively major problems.
Firstly, a constant is likely to have some value which needs to be used
or matched somewhere else. A READ_ONLY flag mis-typed as REED_ONLY could
be interpreted as int(0) (i.e. intval('REED_ONLY')) and cause a
catastrophic error.
Secondly, keywords are also bare words, and any expression can be a
statement. Thus the following is an infinite loop, no matter what
blahblah() returns:
while(true) {
if ( blahblah() ) {
brek;
}
}
Obviously, there are other mistakes which could cause such errors, but
this is one that the engine could easily pick up on and protect the user.
CONS
Like most changes, the downside is a break in compatibility.
As far as I can make out, the current behaviour is actually for
compatibility back as far as PHP 3 (correct me if I'm wrong, I didn't
dig far).
I'm not aware of any notice officially deprecating barewords-as-strings,
but nor can I find many references to it in the manual at all. Its use
for array keys has been explicitly discouraged in the manual since some
time in 2001. [1]
Outside code golf, I'd be very surprised if any code written or updated
in the last 10 years deliberately uses this "feature", and I think
changing it in PHP 7 is justifiable given the benefits to maintainers of
even the simplest non-OO, non-namespaced code.
What do people think?
[1]
http://web.archive.org/web/20010614144157/http://www.php.net/manual/en/language.types.array.php#language.types.array.donts
Regards,
--
Rowan Collins
[IMSoP]
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php