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?
// 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.
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.
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)
if($FOO) do_something();
Just using FOO takes it as a value rather than the variable you defined. Better to use PHP's defined.
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);
}
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 }
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
}
Related
So I'm using a PHP framework called fuelphp, and I have this page that is an HTML file, so I can't use PHP in it. I have another file that has a top bar in it, which my HTML file will call through ajax.
How do I check if a constant exists in PHP?
I want to check for the the fuelphp framework file locations.
These are the constants I need to check for (actually, I only have to check one of them):
define('DOCROOT', __DIR__.DIRECTORY_SEPARATOR);
define('APPPATH', realpath(__DIR__.'/fuel/app/').DIRECTORY_SEPARATOR);
define('PKGPATH', realpath(__DIR__.'/fuel/packages/').DIRECTORY_SEPARATOR);
define('COREPATH', realpath(__DIR__.'/fuel/core/').DIRECTORY_SEPARATOR);
require APPPATH.'bootstrap.php';
edit:
I realized that these aren't variables they are constants...
First, these are not variables, but constants.
And you can check their existence by using the defined() function :
bool defined ( string $name )
Checks whether the given constant exists and is defined.
Use defined() function, for example:
if (defined('VAR_NAME')) {
// Something
}
Check using defined('CONSTANT') function.
An example from the manual:
<?php
/* Note the use of quotes, this is important. This example is checking
* if the string 'TEST' is the name of a constant named TEST */
if (defined('TEST')) {
echo TEST;
}
?>
here's a cooler & more concise way to do it:
defined('CONSTANT') or define('CONSTANT', 'SomeDefaultValue');
credit: daniel at neville dot tk
https://www.php.net/manual/en/function.defined.php#84439
I take it you mean CONSTANTS not variables! the function is defined();
see here: defined
With defined you'll have to do something like that:
if (defined("CONST_NAME"))
$value = CONST_NAME;
This will work, but you'll could get an annoying error message in your code editor (in my case Visual Studio Code with PHP Inteliphense extension) for the second line, since it wont find CONST_NAME.
Another alternative would be to use the constant function. It takes an string as the constant name and returns null if the constant is not defined:
$value = constant("CONST_NAME");
if ($value != null)
{
// Use the value ...
}
Since you passed the const name as a string, it wont generate an error on the code editor.
I'm currently programming a website (in PHP4). I plan to save values, which do not change during runtime, in constants. Those are for example the version number of login-data for the database.
Question 1: are there any (security relevant) problems that can arise from saving data in constants?
At the moment I do the following to define and call the constant:
define("VERSION", "1.0");
echo "Current version: ".VERSION."."; // Result: "Current version: 1.0."
There is one thing that annoys me: In case a constant is not defined, the "wrong" variable name is returned instead of e.g. NULL.
define("VERSION", "1.0");
echo "Current version: ".VERSIONXXX."."; // Result: "Current version: VERSIONXXX."
One solution I found to get an error message and the return value "NULL" when I accidently entered a wrong constant name is using the function constant():
define("VERSION", "1.0");
echo "Current version: ".constant("VERSIONXXX")."."; // Result: "Current version: ."
Question 2: Can I prevent in a different way, that PHP returns the name of the non-existing variable?
Question 3: Should the value of a constant in PHP always be returned using the function constant()?
If you attempt to use a constant that does not exist, PHP automagically assumes it is a string instead, which is why you see VERSIONXXX.
IIRC it throws a warning if you're error reporting is at the appropriate level. The best solution here is to ensure your code utilizes the proper constant names.
If you know the name of the constant, it's easiest/best to use it directly. echo MY_CONSTANT
If you don't know the name of the constant (e.g. it's name is in a variable), use constant():
$name = 'MY_CONSTANT';
echo constant($name);
In reverse Order:
Question 3: No
Question 2: Not really, but you can make adjustments.
because of (Question 1:) error_reporting. You PHP webserver is configured hide some errors. If you add
error_reporting(E_ALL);
to your scripts head, you will get a
Use of undefined constant MY_CONST - assumed 'MY_CONST'
Error. Unfortunately it's a problem coming out of PHP's long history, that constants can be interpreted as strings.
If you can not be shure a constant was set in the first place you can use defined
if(defined('MY_CONSTANT') {
//do something
}
But my personal opinion there shouldn't be many cases to need this, since the word constant alone implies a garanteed presence. The only exception I can think of is the typical header test.
if(!defined('MY_APP_IS_PRESENT')) {
die('You can not call this file on its own, please use index.php.');
}
And one last tipp: Go and make yourself a errorhandler function, maybe even with firephp?
Well, you could always use defined function to make sure the constant exists. Combined with a ternary statement, you could simply echo an empty string, something like:
echo defined( VERSION ) ? VERSION : "";
Not the best answer, but workable?
PHP manual for defined() is at http://php.net/manual/en/function.defined.php
Stupid question - I'm surprised this one has bitten me. Why do undefined constants in PHP evaluate to true?
Test case:
<?php
if(WHATEVER_THIS_ISNT_DEFINED)
echo 'Huh?';
?>
The above example prints 'Huh?'
Thanks so much for your help! :)
Try defined('WHATEVER_THIS_ISNT_DEFINED')
When PHP encounters a constant that is not defined, it throws an E_NOTICE, and uses the constant name you've tried to use as a string. That's why your snippet prints Huh!, because a non-empty string (which is not "0") will evaluate to true.
From the 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.
If you set your error reporting level to report E_NOTICEs, which is a good practice during development, you will also see the notice thrown.
PHP Constant Syntax
defined()
Casting to Boolean
error_reporting
error_reporting() function
From the 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").
Basically, if WHATEVER_THIS_ISNT_DEFINED isn't defined, PHP interprets it as "WHATEVER_THIS_ISNT_DEFINED". Non-empty strings evaluate to true, so your expression will always pass (unless WHATEVER_THIS_ISNT_DEFINED is defined and set to a falsey value.)
This is, frankly, stupid behaviour. It was implemented, I believe, to allow things like $foo[bar] to work when the programmer should have used $foo['bar']. It's illogical behaviour like this that makes people think PHP isn't a real programming language.
The way to test whether a constant is defined is with defined.
Undefined constants are treated as strings by PHP: docs. Taking that fact, think it through in English language:
If "WHATEVER_THIS_ISNT_DEFINED", then do something.
... it is logical that it is "true" - you aren't comparing anything to anything else.
That is why, when doing if statements, it is best practice to include a specific evaluation. If you're checking for false, put it in the code: if (something === false) vs if (something). If you're checking to see if it is set, use isset, and so on.
Also, this highlights the importance of developing with notices and warnings enabled. Your server will throw a notice for this issue:
Notice: Use of undefined constant
MY_CONST - assumed 'MY_CONST' in
some_script.php on line 5
Turn on notices and warnings to develop, turn them off for production. Can only help!
Try defined(). If it's not defined then the constant assumes it's simply text.
Note that constant name must always be quoted when defined.
e.g.
define('MY_CONST','blah') - correct
define(MY_CONST,'blah') - incorrect
also
<?php
if (DEBUG) {
// echo some sensitive data.
}
?>
and saw this warning:
"Use of undefined constant DEBUG - assumed 'DEBUG'"
A clearer workaround is to use
<?php
if (defined('DEBUG')) {
// echo some sensitive data.
}
?>
See http://php.net/manual/en/language.constants.php
It's not just constants, it is a much broader issue with PHP's parsing engine. (You ought to see warnings in your logs.)
In PHP, "bare words" that it doesn't recognize are generally treated as strings that happen to be missing their quotes, and strings with a non-zero length tend to evaluate to true.
Try this:
$x = thisisatest ;
$y = "thisisatest";
if($x == $y){
echo("They are the same");
}
You should see "They are the same".
Old question, but in addition to defined() you can also use strict type checking using ===
<?php
if(WHATEVER_THIS_ISNT_DEFINED === true) // Or whatever type/value you are trying to check
echo 'Huh?';
In a piece of code I found the following conditional statement:
if ( !defined('MY_CONSTANT') || MY_CONSTANT !== false )
and I am wondering what this may achieve that is not achieved by simply stating:
if ( MY_CONSTANT !== false )
..
is it not so, that in case MY_CONSTANT !== false then it MUST also be defined, making the first argument of the first example superfluous, or am I missing something?
If the constant may be undefined at that point, trying to access it will produce a warning on properly configured servers. You don't want those filling up your error logs, hence the defined() check.
The or conditional stops evaluating as soon as one of the conditions is true.
Since the conditions are evaluated left to right, and trying to check an undefined constant yelds an exception, you first check if it is defined, and then for its value.
If the constant is not defined, the if statement exits, and doesn't try to check the value.
Your version and the first version are not the same:
If it is not defined, the first condition of the first version will be true, and it will 'trigger'.
If it is not defined, your version will be false. (well, at least raise an error ;) )
no, because if MY_CONSTANT is not defined, PHP will give you an error message :
Notice: Use of undefined constant MY_CONSTANT
If MY_CONSTANT is not defined, PHP will do two things:
Log and/or display an error when you try to use it
Interpret MY_CONSTANT as if it were the literal string "MY_CONSTANT"
Yesterday, I posted an answer to a question that included several (unknown to me at the time) very bad code examples. Since then, I've been looking at my fundamental knowledge of PHP that allowed me to think that such code is possible. This brings me to a question that I can't seem to find an answer to:
If I want to check for whether or not a variable has anything set, is it a valid practice to not use isset() or another helper function? here's a "for instance":
if($not_set){
//do something
} else {
//do something else
}
Rather than...
if(isset($not_set)){
//do something
} else {
//do something else
}
From the name of the variable, you can see that this variable is not set. Therefore the conditional would be false and the else portion would run. Up until now I have been using this practice, but after the posts yesterday, I now have an inkling that this is wrong.
Here's why I thought that it would be an ok practice to leave out the isset() function above. From PHP manual:
The if construct is one of the most
important features of many languages,
PHP included. It allows for
conditional execution of code
fragments. PHP features an if
structure that is similar to that of
C:
if (expr) statement
As described in the section about
expressions, expression is evaluated
to its Boolean value. If expression
evaluates to TRUE, PHP will execute
statement, and if it evaluates to
FALSE - it'll ignore it. More
information about what values evaluate
to FALSE can be found in the
'Converting to boolean' section.
And from the 'Converting to boolean section':
When converting to boolean
, the following values are considered
FALSE:
...
* the special type NULL (including unset variables)
Why would the manual go out of its way to state that unset variables are included if this is a bad practice? If it's unset, it gets converted to NULL and therefore is evaluated properly by the conditional. Using isset() will find the same result, but will take extra cycles to do so.
Have I been wrong this whole time, and if so, why? (And just how bad it is, maybe?)
If the variable is not set you get a Notice. If you use isset() you don't get a notice. So from an error reporting point of view, using isset() is better :)
Example:
error_reporting(E_ALL);
if($a) {
echo 'foo';
}
gives
Notice: Undefined variable: a in /Users/kling/test on line 5
whereas
error_reporting(E_ALL);
if(isset($a)) {
echo 'foo';
}
does not output anything.
The bottom line: If code quality is important to you, use isset().
It's okay but not good practice to use if to check for a set variable. Two reasons off the top of my head:
Using isset makes the intent clear - that you're checking whether the variable is set, and not instead checking whether a condition is true.
if ($not_set) will evaluate to false when $not_set is actually set but is equal to boolean false.
You will run in to problems if your variable is set, but evaluates to FALSE, like the following:
the boolean FALSE itself
the integer 0 (zero)
the float 0.0 (zero)
the empty string, and the
string "0"
an array with zero elements
an object with zero member
variables (PHP 4 only)
the special type NULL (including
unset variables)
SimpleXML objects created from empty
tags
Taken from the PHP manual.
Basically, using isset() is showing that you are explicitly checking if a variable exists and is not NULL, while the structure of your if statement only checks if the variable is true. It is more clear and less error-prone.
It is a common practise, but is not good -- you should always use isset!
If your $not_set is set, and is a bool with the value false, your "test" will fail!
isset works as a guard preventing you from using variables that do not actually exist.
if (isset($foo)) and if ($foo) do not mean the same thing. isset just tells you if the variable actually exists and if it's okay to use it, it does not evaluate the value of the variable itself*.
Hence, you should usually use one of these two patterns:
If the variable is sure to exist and you just want to check its value:
if ($foo == 'bar')
If the variable may or may not exist, and you want to check its value:
if (isset($foo) && $foo == 'bar')
If you're just interested that a variable is set and evaluates to true, i.e. if ($foo), you can use empty:
if (isset($foo) && $foo)
// is the same as
if (!empty($foo))
* it does check for null, where null is as good as not being set at all