获取PHP中动态选择的类常量的值

Posted

技术标签:

【中文标题】获取PHP中动态选择的类常量的值【英文标题】:Get value of dynamically chosen class constant in PHP 【发布时间】:2011-09-03 01:50:28 【问题描述】:

我希望能够做这样的事情:

class ThingIDs

    const Something = 1;
    const AnotherThing = 2;


$thing = 'Something';
$id = ThingIDs::$thing;

这不起作用。有没有一种直接的方法来做等效的事情?请注意,我坚持上课;它在我无法重写的库中。我正在编写在命令行上接受参数的代码,并且我真的希望它采用符号名称而不是 id 数字。

【问题讨论】:

你能试试ThingIDs::$thing吗? 已经试过了。给我一个解析错误,而不是一个致命的运行时错误。 【参考方案1】:

使用constant()函数:

$id = constant("ThingIDs::$thing");

【讨论】:

旁注:如果要先检查常量是否定义,则为defined("ThingIDs::$thing"); 或 $id = constant("self::$thing"); 与此类似,$id = constant(sprintf('%s::%s', ThingIDs::class, $thing)); @DavidBaucum 你为什么要过度复杂化呢?该请求非常简单,不涉及外部的、用户可操作的输入。除此之外,您正在调用另一个函数,因为我猜您不喜欢将字符串与分隔符连接起来? 根据您的用例,我的解决方案不那么复杂。特别是如果您使用 PSR-4 自动加载,那么在您的代码中到处都拼写 FQDN 可能会很丑陋。通过在文件顶部使用use,然后使用::class 方法神奇地获取FQDN,提高了可读性。【参考方案2】:

使用反射

$r = new ReflectionClass('ThingIDs');
$id = $r->getConstant($thing);

【讨论】:

反射确实提供了对类、方法等的很多洞察力,似乎很多人都害怕采取这一步来理解它们。很好的答案。 @mikemackintosh 我已采取措施了解它们,但在性能影响方面与公认的答案相比并没有看到太多。这是我有兴趣知道的。实例化一个新类似乎比简单地静态调用一个常量对性能的影响更大。您对此有何看法?【参考方案3】:

如果你使用命名空间,你应该在类中包含命名空间。

echo constant('My\Application\ThingClass::ThingConstant'); 

【讨论】:

【参考方案4】:

辅助函数

你可以使用这样的函数:

function class_constant($class, $constant)

    if ( ! is_string($class)) 
        $class = get_class($class);
    

    return constant($class . '::' . $constant);

它需要两个参数:

类名或对象实例 类常量名

如果传递了一个对象实例,则推断其类名。如果您使用 php 7,则可以使用 ::class 传递适当的类名,而无需考虑命名空间。

示例

class MyClass

    const MY_CONSTANT = 'value';


class_constant('MyClass', 'MY_CONSTANT'); # 'value'
class_constant(MyClass::class, 'MY_CONSTANT'); # 'value' (PHP 7 only)

$myInstance = new MyClass;
class_constant($myInstance, 'MY_CONSTANT'); # 'value'

【讨论】:

【参考方案5】:
<?php

class Dude 
    const TEST = 'howdy';


function symbol_to_value($symbol, $class)
    $refl = new ReflectionClass($class);
    $enum = $refl->getConstants();
    return isset($enum[$symbol])?$enum[$symbol]:false;


// print 'howdy'
echo symbol_to_value('TEST', 'Dude');

【讨论】:

【参考方案6】:

如果您有对类本身的引用,那么您可以执行以下操作:

if (defined(get_class($course). '::COURSES_PER_INSTANCE')) 
   // class constant is defined

【讨论】:

【参考方案7】:

我的问题与这个主题类似。当你有对象但没有类名时,你可以使用:

$class_name = get_class($class_object);
$class_const = 'My_Constant';

$constant_value = constant($class_name.'::'.$class_const);

【讨论】:

【参考方案8】:

我知道我来晚了,但我希望这能有所帮助。

根据Phil的回答,我创建了一个可以扩展的默认枚举器类。

class DefaultEnum

    static public function getConstantText(string $constant)
    
        try 
            // Get child class name that called this method
            $child_class = get_called_class();

            $reflection = new ReflectionClass($child_class);
            $const = $reflection->getConstant($constant);

            return $const;
         catch (\ReflectionException $e) 
            // ...
        
    


class CustomEnum extends DefaultEnum

    const something = 'abcd';
    const something2 = 'ABCD';

你可以这样调用这个方法

CustomEnum::getConstantText('something');

它将返回'abcd'

函数get_called_class()是一个返回调用该方法的类名的函数,它专门用于静态方法。

在这种情况下,$child_class 的值将是 CustomEnum::class。 ReflectionClass 接受字符串和对象作为参数。

【讨论】:

以上是关于获取PHP中动态选择的类常量的值的主要内容,如果未能解决你的问题,请参考以下文章

PHP魔术常量

php魔术常量

c#中的静态变量,怎么通过反射的方式获取指定变量名称的值呢?比如说一个const类型的常量:con

php魔术常量

在php中获取类常量名称?

PHP中的动态常量名