Undefined Constant Is a String?

Wed, 20 Dec 2006 20:16 UTC

From the I-noticed-this-one-day-while-looking-at-a-co-worker’s-code department comes a tale about the use of undefined constants in PHP—and relying on this twisted “feature” to make an application function properly.

So, there I was, looking over the shoulder of a colleague, trying to help him debug an application, when I saw something that struck me as quite odd.

“Where is that constant defined?” I asked, pointing to the screen.

“What constant?”

It was plain as day to me. “That constant.”

“Oh, that’s not a constant. It’s a string.”

“No, it’s not,” I retorted. “If it’s a string, why are there no quotation marks. You should be getting an error about an undefined constant.”

“No, it’s a feature of PHP. You don’t have to use the quotation marks.”

And then it struck me: If this is a feature, it’s most likely the dumbest feature I’ve ever seen. Perhaps Jamie of Yet Another Web Development Blog has something there . . .

Nevertheless, after digging around some, I found this in the PHP manual:

If you use an undefined constant, PHP assumes that you mean the name of the constant itself, just as if you called it as a string (CONSTANT vs “CONSTANT”). An error of level E_NOTICE will be issued when this happens. See also the manual entry on why $foo[bar] is wrong (unless you first define() bar as a constant).
PHP: Constants

Hmm. So, if $foo[bar] is wrong, remind me again why this is even a feature? In my opinion, it should return, at the least, an E_WARNING error. Instead, the error level is E_NOTICE, but let’s examine what happens when the millions of people running distribution versions of PHP use this “feature.”

Most distributions use the php.ini-dist file instead of the php.ini-recommended file. This means that error_reporting is set to E_ALL & ~E_NOTICE and notices are not generated or displayed, so users will never know about their undefined constants. My colleague was using the PHP distribution for Debian, Debian’s default php.ini settings, and, thus, was never aware of the notices generated by the use of undefined constants. What’s worse is that the code my colleague was using was not his own—it was third-party, open source software!

Here’s why it’s bad to rely on this behavior. In the follow snippet of code, I expect that foo will always be the string “foo.” The problem is that I’m really using an undefined constant.

<?php
 
$var = foo;
my_func($var);
 
?>

When I pass $var to my_func(), the function may do something that expects the value to be the string “foo,” but what if the core developers decide to add a constant with the name foo and assign it a value. Now, $var is no longer the string “foo.” It’s whatever the language has defined it to be. That’s an unlikely scenario, but what if another programmer in my team decides to define the constant foo (this is much more likely)? Now, the code mysteriously breaks, and it’s difficult to find the problem (especially because E_NOTICE is turned off). Even worse: what if I’m using third-party code that relies on this behavior, and I’ve integrated it into my application that has some global constants by the same names set?!

So, the lessons learned from this are:

  1. Always develop applications using an error level of E_ALL or E_STRICT; when you encounter notices, fix them because they could indicate problems with your logic that may not immediately present themselves
  2. If you want a string value, use quotation marks (single or double), otherwise, treat your “string” as a constant because that’s what it is
  1. Don’t rely on the use of undefined constants—they aren’t NULL or empty; instead, they are actually the string value of the constant name

    Note that this behavior of constants continues to exist even in the latest versions of PHP, including 5.2 and 6.0.0-dev. Why? I don’t know.


10 Responses to “Undefined Constant Is a String?”

[...] Original post by Ben Ramsey [...]

Comment by Planeta Debian » Undefined Constant Is a String?
Wed, 20 Dec 2006 at 21:53 UTC | Permalink

>Note that this behavior of constants continues to exist even in the latest versions of PHP,
>including 5.2 and 6.0.0-dev. Why? I don’t know.

There are 0 reasons to change it except for if you’re to break tons of poorly written apps (even if they deserve it).

Comment by tony2001
Wed, 20 Dec 2006 at 21:58 UTC | Permalink

Slap your coworker with a E_ALL|E_STRICT bat and don’t waste so much ink to explain something that exists since years ;-)

The fact that you ask if it is really a feature makes me wonder … bah :)

Comment by Pierre
Wed, 20 Dec 2006 at 22:08 UTC | Permalink

Unquoted strings were a feature of PHP before PHP 3.0,
quoting strings was optional if there was no whitespace within the string.

With the introduction of constants in PHP 3 this has become a backward
compatibility burden, but even with the warning added in at least 4.0
(or was it already in 3.0?) there is still lots of code out there that
relies on this.

But on the other hand this one was the easiest to fix and the least likely to break of the NOTICE level warnings that i have encountered in making legacy code E_NOTICE free, there are way more serious things reported by it like use of uninitialized variables etc.

So always coding with E_NOTICE on is a must for any serious PHP developer IMHO, and just the fact that you inherited legacy code
to maintain is no excuse to have it set to off … but that might just be me …

Comment by hartmut
Wed, 20 Dec 2006 at 22:19 UTC | Permalink

PHP Error reporting

Yet more reasons why error reporting should be set to E_ALL.

I have found the easiest way to do this in WAGERplayer is to add an error_reporting(E_ALL) to your scripts, just after including admin_config.php, as too much of the old stuff will emit a lot

Comment by BEToptions
Wed, 20 Dec 2006 at 23:29 UTC | Permalink

Ben Ramsey’s Blog: Undefined Constant Is a String?

Comment by PHPDeveloper.org
Thu, 21 Dec 2006 at 13:19 UTC | Permalink

You will see this a lot in legacy code that many developers have worked on. The current codeset that i am working on has a ton of $foo[bar] and throws many errors about undefined constants. Time to cleanup and use proper methods.

Comment by Joseph Crawford
Thu, 21 Dec 2006 at 15:54 UTC | Permalink

This problem has bit me before too.

The worst is when people do conditional checks against undefined constants…

if(SUPER_CONSTANT){
do this
}

It will always pass if the constant isn’t defined. Now I always develop with notices turned on.

Comment by Matt
Thu, 21 Dec 2006 at 23:01 UTC | Permalink

Am I showing my age when I was really confused that you were confused with the contants parsed as strings when not defined?

Comment by terry chay
Sat, 23 Dec 2006 at 23:54 UTC | Permalink

Old post, but for those coming across this page who are also wondering “why?”, the feature was inspired by Perl. Barewords in Perl become strings, unless you use the “strict” module. The feature, both in Perl and PHP, is not officially deprecated but is considered harmful.

Reference:
Wall, Larry; “Programming Perl”, 3rd Ed; p860

Comment by kanenas
Mon, 29 Jun 2009 at 1:04 UTC | Permalink

Leave a Comment

XHTML: You can use these tags:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>
APPROVAL: Comments may require approval. Please be patient.