Friday, 10 August 2018

PHP Question: Defining Constants

Question

What does the following code do?

define("MY_CONSTANT", array(1,2,3,4,5))
Answer
If this code is run it will produce the following error:
Warning: Constants may only evaluate to scalar values in test.php on line x
This is because only scalar values can be assigned to constants. A scalar value is any integer, float, string or boolean value and does not include arrays, objects or resources. Trying to set any non-scalar value as a constant will produce this error.
If we went on to var_dump() the constant defined above we would get back a string containing "MY_CONSTANT". This is because if you try to retrive any constant value that hasn't been set PHP will try to evaluate it as a string. What this means is that if you try to do a simple boolean test for the constant (see the example below) it will evaluate to true.
  1. if (MY_CONSTANT) {
  2. echo 'constant set, or not...';
  3. }
We can test for the existence of the constant in a couple of ways. We already know that any constant that isn't defined is cast as a string so we can test for this by doing a type comparison between the constant and a string of the constant name. If the constant is defined then this will equal false.
var_dump(MY_CONSTANT === 'MY_CONSTANT'); // true if constant not set
However, when we do this we get the following notice about using an undefined constant and that PHP has cast it as a string.
Notice: Use of undefined constant MY_CONSTANT - assumed 'MY_CONSTANT' in test.php on line x
The built in PHP function defined() can be used to test for the existence of a constant value. This accepts a string of the constant name and will return a boolean value that shows if the constant has been set or not. This also avoids the need to try out the constant itself and get a notice if it isn't defined.
var_dump(defined('MY_CONSTANT')); // false
There are a couple of ways to get around the restriction of only allowing scalar values to be used in constants. The first way is to use serialize() to convert the array into a string before setting it as a constant.
  1. define("MY_CONSTANT", serialize(array(1,2,3,4,5)));
  2. var_dump(defined('MY_CONSTANT')); // prints truw
  3. print_r(unserialize(MY_CONSTANT));
We could also use json_encode() here, which will have the same effect. This probably isn't the best way to set constant values, although it is perfectly allowed in PHP. The other way to get a constant with an array is to use a static variable in a class. This is effectively a constant as it won't (at least it shouldn't) be changed during the execution of the script.
  1. class Constants {
  2. public static $myConstant = array(1, 2, 3, 4, 5);
  3. }
  4.  
  5. print_r(Constants::$myConstant);
This will print out the array in full.
Note that you can't set arrays to be constants in classes as you will get a fatal error instead of a warning. For example, the following script.
  1. class Constants {
  2. const MY_CONSTANT = array(1, 2, 3, 4, 5);
  3. }
  4.  
  5. print_r(Constants::MY_CONSTANT);
Will produce the following error when run.
Fatal error: Arrays are not allowed in class constants in test.php on line x

0 comments:

Post a Comment