Alex
Alex

Reputation: 68492

PHP undefined constant testing

In PHP if I define a constant like this:

define('FOO', true);
if(FOO) do_something();

The method do_something gets executed as expected.

But if I don't define the BOO constant below:

if(BOO) do_something();

Then do_something also gets executed. What's going on here?

Upvotes: 9

Views: 4484

Answers (7)

Mike Lewis
Mike Lewis

Reputation: 64147

PHP will automatically make the guess that you meant the string format, which a string will return true.

However you should use the defined method:

bool defined ( string $name )

So it would be:

if(defined('BOO')) {\\code }

Upvotes: 2

alex
alex

Reputation: 490243

// BOO has not been defined

if(BOO) do_something();

BOO will be coerced into the string BOO, which is not empty, so it is truthy.

This is why some people who don't know better access an array member with $something[a].

You should code with error_reporting(E_ALL) which will then give you...

Notice: Use of undefined constant HELLO - assumed 'HELLO' in /t.php on line 5

You can see if it is defined with defined(). A lot of people use the following line so a PHP file accessed outside of its environment won't run...

<?php defined('APP') OR die('No direct access');

This exploits short circuit evaluation - if the left hand side is true, then it doesn't need to run the right hand side.

Upvotes: 13

SherylHohman
SherylHohman

Reputation: 17900

Another option is to use php's constant() function, as in:

if (constant('BOO')) doSomething();

Remember to enclose the constant's name in quotes.

Here is a PHP replit demonstrating the examples below.

Ap per the php docs, if the constant is defined, its value is returned; otherwise, null is returned.

Since null is falsey, this will behave as expected.
This can be used in cases where you need to know if something is explicitly defined as true (or at lease a truthy value) vs either not defined, or defined with a falsey value. This works particularly well when having a variable defined is the exception, or having it undefined could be a security risk.

if (constant('IS_DEV')) {
  // *Remember to enclose the constant's name in quotes.*
  // do stuff that should only happen in a dev environment
  // By Default, if it didn't get defined it is, as though, 'false'
}

Using constant() when checking against variables is a good practice to mitigate against security risks in certain situations. For example, printing out php info only if a certain constant is (defined and) TRUE.
As your question shows, PHP's string conversion would expose details if somehow the constant did not get defined.

Alternately, you could:

if (defined('IS_DEV') && (IS_DEV)) {
  // *Remember to enclose the constant's name in quotes for the FIRST operator.*
  // do stuff that should only happen in a dev environment
}

Another method that would work is to use === or !==, which tests exact equality (including type), without performing typecast a conversion.

if (IS_DEV === true)) {
  // do stuff that should only happen in a dev environment
}

Upvotes: 0

Anomie
Anomie

Reputation: 94794

If you enable error logging, you'll see an error like the following:

PHP Notice: Use of undefined constant BOO - assumed 'BOO' in file at line N

What's happening is that PHP is just arbitrarily assuming that you meant to use 'BOO' and just forgot the quotes. And since strings other than '' and '0' are considered "true", the condition passes.

Upvotes: 6

Jorg
Jorg

Reputation: 7250

If it's not the existance of the constant you want to test, but if you want to test the value of the constant you defined, this might be a better way: if(BOO === true) or if(BOO === false)

Upvotes: 3

JRL
JRL

Reputation: 78003

PHP is dynamically typed. You can achieve what you're trying to do with a function such as this:

function consttrue($const) {
    return !defined($const) ? false : constant($const);
}

Upvotes: 2

Rasika
Rasika

Reputation: 1998

if($FOO) do_something(); 

Just using FOO takes it as a value rather than the variable you defined. Better to use PHP's defined.

Upvotes: 2

Related Questions