php constant case-insensitive issue - php

I'm overriding a constant with case in-sensitive parameter. But php doesn't give me "constant already defined" error. I've enabled E_ALL,E_STRICT errors.
Example:1
define('ONE',1000);
define('one',2000,true);
echo ONE; // prints 1000
echo one; // prints 2000
In the second line, i'm making 'one' as another constant with case in-sensitive, which means redefining 'ONE'. But PHP gives no error/warning.
Example:2
define('ONE',1000,true);
define('one',2000);
echo ONE; // prints 1000 with constant already defined notice
echo one; // prints 1000
Here i can get error notice.
What's the difference between these two code blocks.?

From the documentation:
Note: Case-insensitive constants are stored as lower-case.
Thus, when trying to define the lower-cased version of the constant in your second example, the constant is already defined due to the prior case-insensensitive definition of a constant with the same name.
define('ONE', 1000, true); // defines strtolower("ONE") = "one"
define('one', 2000); // error redefining "one"
In the first scenario, there is no such collision:
define('ONE', 1000); // defines "ONE"
define('one', 2000, true); // defines strtolower("one") = "one"

The third Parameter in the define function is the case_insensitive option.
http://php.net/manual/de/function.define.php
In the first Example the constant ONE ist defined. And the constant one with case_insensitive true. Means you got a variable you can reach via ONE and a variable you can reach via oNe,One,oNE etc.
In the secound Example you first define a constant ONE with case_insensitive true and then the constant one. But this time all possible names (OnE,oNe,one) are already given, so the interpreter gives you a error notice

Related

PHP: undefined constant while defining it

I'm getting the following error in PHP:
Notice: Use of undefined constant CONSTANT
on the exact line where I define it:
define(CONSTANT, true);
What am I doing wrong? I defined it, so why does it say "Undefined constant"?
You need to quote the string which becomes a constant
define('CONSTANT', true);
The best way to understand what are you doing wrong is to read PHP manual.
Here is definition of define function.
bool define ( string $name , mixed $value [, bool $case_insensitive = false ] )
So the first argument must be a string.
If you write it like that you are using the value of an already defined constant as a constant name.
What you want to do is to pass the name as a string:
define('CONSTANT', true);
Although not really, strictly relevant to your case, it is most desirable to first check that a CONSTANT has not been previously defined before (re)defining it.... It is also important to keep in mind that defining CONSTANTS using define requires that the CONSTANT to be defined is a STRING ie. enclosed within Quotes like so:
<?php
// CHECK THAT THE CONSTANTS HASN'T ALREADY BEEN DEFINED BEFORE DEFINING IT...
// AND BE SURE THE NAME OF THE CONSTANT IS WRAPPED WITHIN QUOTES...
defined('A_CONSTANT') or define('A_CONSTANT', 'AN ALPHA-NUMERIC VALUE', true);
// BUT USING THE CONSTANT, YOU NEED NOT ENCLOSE IT WITHIN QUOTES.
echo A_CONSTANT; //<== YIELDS:: "AN ALPHA-NUMERIC VALUE"
See below currect way to define constant
define('Variable','Value',case-sensitive);
Here Variable ==> Define your Constant Variable Name
Here Value ==> Define Constant value
Here case-sensitive Defult value 'false', Also you can set value 'true' and 'false'

Why is it that PHP constants declared as case insensitive can be reassigned?

Lately I found a bug in a huge system I'm working on caused by this behaviour:
Consider this:
define('TEST',10);
echo TEST; // prints 10
define('TEST',20); // Error -> already assigned.
But if we declare it as insensitive:
define('TEST',10,true);
echo TEST; // prints 10
define('TEST',20); // no error ????
echo TEST; //prints 20
I understand what are the differences between CS and CI and I realise that I'm creating a new constant in the second definition. But I really don't
understand why is that possible?
Isn't that a violation of the constant concept?
Does this behaviour has any applications or is it a PHP weird thing...
Because your first constant (which you saved as case-insensitive) is saved in lowercase as you can read it in the manual:
Note:
Case-insensitive constants are stored as lower-case.
Means since it is case-insensitive all variants of lower and upper case from test, which are != TEST in uppercase are corresponding to the value 10. If it is TEST which is case-sensitive means every letter in uppercase it is the constant with the value 20.
E.g.
Test -> 10
tEst -> 10
tesT -> 10
TEST -> 20
And a "special case" is also TEST if you use it before you define your case-sensitive constant it is still pointing to the constant with the value 10.
When you are doing define('TEST',10,true); it is stored in lower case but you can access them by both test & TEST.
Now there is no constant with the name of TEST. So when your defining it again the value is set to the constant.
Check it here

When and how to use Constants in PHP?

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

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?
// 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
}

Initializing PHP class property declarations with simple expressions yields syntax error

According to the PHP docs, one can initialize properties in classes with the following restriction:
"This declaration may include an initialization, but this initialization must be a constant value--that is, it must be able to be evaluated at compile time and must not depend on run-time information in order to be evaluated."
I'm trying to initialize an array and having some issues. While this works fine:
public $var = array(
1 => 4,
2 => 5,
);
This creates a syntax error:
public $var = array(
1 => 4,
2 => (4+1),
);
Even this isn't accepted:
public $var = 4+1;
which suggests it's not a limitation of the array() language construct.
Now, the last time I checked, "4+1" equated to a constant value that not only should be accepted, but should in fact be optimized away. In any case, it's certainly able to be evaluated at compile-time.
So what's going on here? Is the limitation really along the lines of "cannot be any calculated expression at all", versus any expression "able to be evaluated at compile time"? The use of "evaluated" in the doc's language suggests that simple calculations are permitted, but alas....
If this is a bug in PHP, does anyone have a bug ID? I tried to find one but didn't have any luck.
PHP doesn't do such operations at compile-time; you cannot assign calculated values to constants, even if all operators are constants themselves. Default values of class members are treated the exact same way. I encountered this behaviour as I tried to assign powers of two to constants:
class User {
const IS_ADMIN = 1;
const IS_MODERATOR1 = 1 << 1; // Won't work
const IS_MODERATOR2 = 0x02; // works
}
This limitation no longer exists as of PHP 5.6
The new feature that enables the previously-disallowed syntax is called constant scalar expressions:
It is now possible to provide a scalar expression involving numeric
and string literals and/or constants in contexts where PHP previously
expected a static value, such as constant and property declarations
and default function arguments.
class C {
const THREE = TWO + 1;
const ONE_THIRD = ONE / self::THREE;
const SENTENCE = 'The value of THREE is '.self::THREE;
public function f($a = ONE + self::THREE) {
return $a;
}
}
echo (new C)->f()."\n"; echo C::SENTENCE; ?>
The above example will output:
4 The value of THREE is 3
Before you throw your arms up at php for this, think about the execution model. In the environment that php is typically used for(and, in fact, designed for), everything is built up, executed, and then thrown away...until the next http request comes in. It doesn't make a lot of sense to waste time doing computations during the parsing/compilation phase. The engine needs to be very swift here in the general case.
But, you're right, that quote from the manual does say "evaluate". Maybe you should open a documentation ticket.
Edit march 2014
it looks like php will now support Constant Scalar Expressions in php 5.6:

Categories