3

I found an elaborate reference in this SO Q&A on how to check whether variables exist.

It is mentioned that to check whether a class has a certain property, one uses (as documented at php.net):

$check = property_exists('MyClass', 'property_name');

Also, for 'constants' that are 'defined', one could use:

$check = defined('MY_CONSTANT');

Question: how about a const in a class?

To elaborate... I have a class which I use in several projects, (minimal example):

class ProjectSettings {
    const MY_CONSTANT = 'my constant';
}

I'm writing a new feature which requires a 'project setting' but should apply a default value if the setting does not exist in the class.

Note that the same class is used in several projects (with different values). It would be cumbersome to implement this new const in all existing projects. However, the new feature is in an existing script and I may update older projects with this new version, without also updating the ProjectSettings class (for eaxample if this new feature is not even used). That's why I would like to use feature detection.

I'm thinking in the line of:

if (defined(ProjectSettings::MY_CONSTANT)) {
    $setting = ProjectSettings::MY_CONSTANT;
} else {
    $setting = 'some default value';
}

However, my futile attempts result in:

var_dump(ProjectSettings::MY_CONSTANT);
// string(11) "my constant"
// (as expected)
var_dump(ProjectSettings::MY_OTHER);
// generates a PHP Fatal error

var_dump(defined(ProjectSettings::MY_CONSTANT));
// bool(false)
// (it exists, but is not 'defined', oh well...)
var_dump(defined(ProjectSettings::MY_OTHER));
// generates PHP Fatal error

var_dump(get_class_vars('ProjectSettings'));
// array(0) {
// }
// (MY_OTHER is not there, but neither is MY_CONSTANT...)

var_dump(isset(ProjectSettings::MY_CONSTANT));
// generates a PHP Fatal error

var_dump(null !== ProjectSettings::MY_CONSTANT);
// bool(true)
var_dump(null !== ProjectSettings::MY_OTHER);
// generates a PHP Fatal error

var_dump(constant('ProjectSettings::MY_CONSTANT'));
// string(11) "my constant"
// (as expected)
var_dump(constant('ProjectSettings::MY_OTHER'));
// NULL
// BUT: this generates a PHP Warning

var_dump(property_exists('ProjectSettings', 'MY_CONSTANT'));
// bool(false)
var_dump(property_exists('ProjectSettings', 'MY_OTHER'));
// bool(false)

var_dump(get_defined_constants());
// produces a whole bunch of constants, but not the ones in the class...

The route via constant('ProjectSettings::MY_OTHER') seems promising, but it generates a PHP Warning. I do not want to get warnings and I do not want to suppress them either...

What method did I miss?

Community
  • 1
  • 1
Marten Koetsier
  • 3,389
  • 2
  • 25
  • 36

2 Answers2

8

Passing a string to defined() allows to not rely on reflection:

var_dump(
    defined(ProjectSettings::class."::TEST")
);

This code will print true if the constant exists, and false (without triggering an error) if it doesn't.

Kévin Dunglas
  • 2,864
  • 2
  • 23
  • 39
3

You may use ReflectionClass::getClassConstants() which will output all defined constants or ReflectionClass::getClassConstant() which will output the result for the given constant. Please see the example below.

If you can extend the class, add the static function like:

class myClass
{
    const TEST = 'foo';
    static function getConstants()
    {
        $oClass = new \ReflectionClass(__CLASS__);
        return $oClass->getConstants();
    }
}

output all constants:

var_dump(myClass::getConstants());

If you can't extend the class, you can check with this in any file:

$c = new myClass();
$a = new \ReflectionClass($c);
var_dump( $a->getConstant('FOO'));
// false
var_dump( $a->getConstant('TEST'));
// string(3) "foo"

// Or with a real check: 

if ($a->getConstant('TEST')) {
    // constant is defined
} else {
    // it is not
}
baao
  • 71,625
  • 17
  • 143
  • 203
  • But this does not solve the problem of 'polling' a class that was not updated. With this solution, I still need to update the `ProjectSettings` class everywhere, don't I? But I will try to read more about ReflectionClass. – Marten Koetsier Oct 02 '15 at 16:14
  • You would have to do it once. Wait a second please, I'll update my answer on how to get it from outside of the class – baao Oct 02 '15 at 16:15
  • Updated it @MartenKoetsier. You can check with this, no errors are thrown if it doesn't exist! – baao Oct 02 '15 at 16:19
  • thanks for the hints. I'll give it a try and get back. – Marten Koetsier Oct 02 '15 at 17:06
  • Thanks for pointing me to [`ReflectionClass`](http://php.net/manual/en/class.reflectionclass.php), that does the job. However, the `getConstant` function cannot distinguish between a constant with value false and a non-existing constant. I will get this to work with something like `if (array_key_exists('TEST', $a->getConstants())) { /* do stuff */ }`. – Marten Koetsier Oct 03 '15 at 05:42
  • Well you can implement getConstants() (see the s at the end...) and check if it's in the array then. @MartenKoetsier – baao Oct 03 '15 at 06:26
  • Ahh sorry, just woke up and didn't get the last part of you comment... You already did what I meant. ;-) @MartenKoetsier. – baao Oct 03 '15 at 06:30