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
Related
Is it possible to parse the contents of a constant in PHP?
For example,
define('WHO_AM_I', 'My name is $_SESSION['who_am_i'].'); // setup the constant string
echo eval(WHO_AM_I); // something like this -- but the eval() returns an error
Please note that I do not know the value of the _SESSION var until I actually use the constant later in the script stream.
Thanks.
AMENDED WITH REASON FOR WANTING TO DO THIS
I want to pull "hard coding" out of my script and give the user the ability to configure certain taxonomy in their site. So while I was doing this I also wanted to create a quasi-dynamic constant that I thought I might be able to parse later in the script.
If it can't be done...then it can't be done.
Don't shoot me for asking the question though.
A FINAL COMMENT TO AVOID ALL THIS CONFUSION
The purpose of my question has nothing to do with the eval() function. I am actually regretting having put it in there in the first place.
I put the eval() in the question simply to demonstrate to stackoverflow members that I did a bit if prep on my question rather than asking an open ended -- hey give me a solution without having offered any stab at it myself. So please disregard the eval().
All I want to know is can I somehow craft a define() in an way that makes the assigned value parse-able later in my script. That's it, that's all.
AMENDMENT C
I know I can do the following although I don't want to do it this way:
define('PARSE_ABLE_CONSTANT_PART_A', 'My name is ');
define('PARSE_ABLE_CONSTANT_PART_B', '.');
...later down the script road...
echo PARSE_ABLE_CONSTANT_PART_A . $_SESSION['who_am_i'] . PARSE_ABLE_CONSTANT_PART_B;
I just don't want to do it this way if I can make it slicker using an embedded var in the constant.
This seems really fishy, as other users have pointed out. You could do something like this if you wanted:
define('WHO_AM_I', 'echo \'My name is \'.$_SESSION[\'who_am_i\'];');
eval(WHO_AM_I);
This will always just echo the variable. You need to eval an expression afaik.
Just read your edit. I think you would be better suited with an .ini file, or maybe a static class with static properties. Makes it much more flexible, and you avoid the eval. You are talking user-generated content from what I can see - subjecting that to an eval call seems highly insecure.
A quick example of a static class you could use:
<?php
class myConstants{
public static function _($key){
switch($key){
case "WHO_AM_I":
return "My name is ".$_SESSION['who_am_i'];
break;
case "OTHER_CONSTANT":
// does some other evaluation and returns a string
break;
}
throw new Exception("Constant isn't defined");
}
}
?>
Then you can just echo myConstants::_('WHO_AM_I');
Constants by definition don't allow you to set it with dynamic content.
Here is a quote from the php manual:
As the name suggests, that value cannot change during the execution
of the script
You can see more by going here
You might be thinking of magical constants
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 want to use a global variable setup where they are all declared, initialized and use friendly syntax in PHP so I came up with this idea:
<?
error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
$GLOBALS['debugger'] = 1; // set $GLOBALS['debugger'] to 1
DEFINE('DEBUGGER','$GLOBALS["debugger"]'); // friendly access to it globally
echo "1:" . DEBUGGER . ":<br>";
echo "2:" . ${DEBUGGER}. ":<br>";
echo "3:" . $GLOBALS['debugger'] . ":<br>";
if (DEBUGGER==1) {echo "DEBUG SET";}
?>
generates the following:
1:$GLOBALS["debugger"]:
Notice: Undefined variable: $GLOBALS["debugger"] in /home/tra50118/public_html/php/test.php on line 8
2::
3:1:
How can there be an error with 2: when clearly $GLOBALS["debugger"] IS defined? And then not generate a similar notice with the test at line 10?
I think what I am trying to do is to force PHP to interpret a string ($GLOBALS["debugger"]) as a variable at run time i.e. a constant variable variable
Disclaimer: I agree with the comments, globals are generally a bad idea.
That said, there's a few questions here that are worth answering, and the concept of indirection is useful, so here goes.
${'$GLOBALS["debugger"]'} is undefined. You don't include the leading '$' when using indirection. So, the correct version would be define('DEBUGGER', 'GLOBALS["debugger"]').
But, this doesn't work either. You can only access one level down via indirection. So you can access the array $GLOBALS, but you can't access keys in that array. Hence, you might use :
define('DEBUGGER', 'debugger');
${DEBUGGER};
This isn't useful, practically. You may as well just use $debugger directly, as it's been defined as a global and will be available everywhere. You may need to define global $debugger; at the start of functions however.
The reason your if statement is not causing notices is because you defined DEBUGGER to be a string. Since you aren't trying to use indirection in that line at all, it ends up reading as:
if ("$GLOBALS['debugger']"==1) {echo "DEBUG SET";}
This is clearly never true, though it is entirely valid PHP code.
I think you may have your constants crossed a bit.
DEFINE('DEBUGGER','$GLOBALS["debugger"]'); sets the constant DEBUGGER to the string $GLOBALS["debugger"].
Note that this is neither the value nor the reference, just a string.
Which causes these results:
1: Output the string $GLOBALS["debugger"]
2: Output the value of the variable named $GLOBALS["debugger"]. Note that this is the variable named "$GLOBALS["debugger"]", not the value of the key "debugger" in the array $GLOBALS. Thus a warning occurs, since that variable is undefined.
3: Output the actual value of $GLOBALS["debugger"]
Hopefully that all makes sense.
OK, thanks to all who answered. I think I get it now, I am new to PHP having come form a C++ background and was treating the define like the C++ #define and assuming it just did a string replace in the precompile/run phase.
In precis, I just wanted to use something like
DEBUGGER = 1;
instead of
$GLOBALS['debugger'] = 1;
for a whole lot of legitimate reasons; not the least of which is preventing simple typos stuffing you up. Alas, it appears this is not doable in PHP.
Thanks for the help, appreciated.
You can not use "variable variables" with any of the superglobal arrays, of which $GLOBALS is one, if you intend to do so inside an array or method. To get the behavior you would have to use $$, but this will not work as I mentioned.
Constants in php are already global, so I don't know what this would buy you from your example, or what you are going for.
Your last comparison "works" because you are setting the constant to a string, and it is possible with PHP's typecasting to compare a string to an integer. Of course it evaluates to false, which might be surprising to you, since you expected it to actually work.
Can you undefine or change a constant in PHP?
No. Constants are constant.
Reference: php.net/manual/language.constants.php
I know this is late to the game... but here is one thing that might help some people...
In my "Application.php" file (where I define all my constants and include in all my scripts) I do something like this:
if( !defined( "LOGGER_ENABLED" )){
define( "LOGGER_ENABLED", true );
}
So normally, every script is going to get logging enabled... but if in ONE particular script I don't want this behavior I can simply do this BEFORE I include my Application.php:
define( "LOGGER_ENABLED", false );
If you absolutely need to do this (although I wouldn't recommend it as others have stated) you could always use Runkit.
http://www.php.net/manual/en/function.runkit-constant-redefine.php
http://www.php.net/manual/en/function.runkit-constant-remove.php
No. Once a constant is defined, it can never be changed or undefined.
As not mentioned elsewhere, the uopz extension allows a constant to be deleted via uopz_undefine(), for PHP 5.4+.
The other posters are correct - you can't do this. But perhaps you can move your definition to the point where you know what the best value for the constant would be.
Perhaps you're defining constants in a big list:
define('STRING1','Foo');
define('STRING2', 'Bar');
define('STRING3', 'Baz');
and you want to change the value of STRING2 once you discover a condition. One way would be to defer the definition until you know the correct setting.
define('STRING1','Foo');
// define('STRING2', 'Bar'); -- wait until initialization
define('STRING3', 'Baz');
...
if (condition) {
define('STRING2', 'Bar type 2');
} else {
define('STRING2', 'Bar type 1');
}
The logic setting STRING2 could even be in a different file, later on in your processing.
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
}