检查类常量是否存在

71
如何在 PHP 类中检查常量是否已定义?
class Foo {
    const BAR = 1;
}

是否有类似于property_exists()或者method_exists()的方法可以判断类常量是否存在?还是我可以直接使用defined("Foo::BAR")


1
请参见https://dev59.com/DHNA5IYBdhLWcg3wcdhk。 - Fluffeh
6个回答

86

您可以使用以下代码检查常量是否已定义:

<?php
if(defined('className::CONSTANT_NAME')){
  //defined
}else{
  //not defined
}

3
使用 constant('className::CONSTANT_NAME') 获取它。 - Ismail
1
className 需要完全限定。通常我会使用 $class = get_class($obj); echo defined("$class::CONSTANT_NAME"));。对于更复杂的情况最好使用 ReflectionClass - Kamafeather
2
另外,从PHP> = 7.1.0开始,您还可以使用new \ ReflectionClassConstant($ class,'CONSTANT_NAME');try来捕获类中不存在的常量引发的ReflectionException。 这样检查可能更复杂,但是不会减少正确性; if / else只是根据开发人员的喜好或风格替换为try / catch - Kamafeather
1
使用后期静态绑定,您可以使用 if (defined(static::class . '::CONSTANT')) { $value = static::CONSTANT; } else { throw \RuntimeException('Class '.static::class.' needs constant CONTANT'); } - Radek Pech
晚期静态绑定的示例甚至可以进一步缩短为:defined('static::CONSTANT') - undefined

69

10
请记得将任何命名空间添加到字符串中,例如:defined('my\name\space\ClassName\property')。 - polesen
知道你可以使用 constant('SomeNamespace\SomeClass::CHECKED_CONSTANT') 来获取它的值是很有用的。 - Ormoz

20

您有三种方法可以完成它:

defined()

[PHP >= 4 - 最具向后兼容性的方式]

$class_name = get_class($object); // remember to provide a fully-qualified class name
$constant = "$class_name::CONSTANT_NAME";
$constant_value = defined($constant) ? $constant : null;

注意:在一个私有常量(可能来自PHP7.1)上使用defined()会引发错误:"Cannot access private const"。而使用ReflectionClassReflectionClassConstant将起作用。

ReflectionClass(反射类)

[PHP >= 5]

$class_reflex = new \ReflectionClass($object);
$class_constants = $class_reflex->getConstants();
if (array_key_exists('CONSTANT_NAME', $class_constants)) {
    $constant_value = $class_constants['CONSTANT_NAME'];
} else {
    $constant_value = null;
}

ReflectionClassConstant

[PHP >= 7.1.0]

$class_name = get_class($object); // fully-qualified class name
try {
    $constant_reflex = new \ReflectionClassConstant($class_name, 'CONSTANT_NAME');
    $constant_value = $constant_reflex->getValue();
} catch (\ReflectionException $e) {
    $constant_value = null;
}

没有真正更好的方法。取决于您的需求和用例。


你的第二个例子(PHP >= 5),语法不正确。$class_constants)I{ 应该是 $class_constants)){ - Lucas Bustamante
请注意,defined() 私有注释对于 Trait 特性不适用,因此它可以测试和访问常量。 (从7.1到8.1都是这样工作的)- https://3v4l.org/NQ1f8 还要注意,您只需执行 defined("self::CONSTANT")(请注意引号 ") - jave.web

11

您可以使用该函数:

function constant_exists($class, $name){
    if(is_string($class)){
        return defined("$class::$name");
    } else if(is_object($class)){
        return defined(get_class($class)."::$name");
    }
    return false;
}

或者使用ReflectionClass的替代版本

function constant_exists($class, $name) {
    if(is_object($class) || is_string($class)){
        $reflect = new ReflectionClass($class);
        return array_key_exists($name, $reflect->getConstants());
    }
    return false;
}

如果您需要检查常量值是否存在于类常量中,请使用Reflection类的第二个示例,只需将array_key_exists更改为in_array - Konrad Gałęzowski

1

所以我尝试了这个:

$constants = new \ReflectionClass(App\Namespace\ClassName::class);
if ($constants->getConstant('CONSTANT_NAME')){
    // Do this
} else {
    // Do that
}

它运行得很好。


0
如果你正在使用继承,并且想要在运行时检查常量是否在你想要访问它的地方被定义,你可以使用后期静态绑定(自 PHP 5.3 起)。
$reflectionClass = new \ReflectionClass(static::class);

if (!array_key_exists('MY_CONST', $reflectionClass->getConstants())){
    throw new \LogicException('You must define the constant MY_CONST in the concrete class');
}

这可以作为一种解决方法,确保一个具体的类在类层次结构的其他地方定义了一个必需的常量。显然,我们需要记住这是在运行时完成的警告。但是,如果您在CI流水线中的测试中添加此检查,这就足够好的解决方法了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接