编程

PHP 8.3 新特性预览: 动态访问类常量及 Enum 成员

505 2023-02-06 09:18:12

PHP 8.3 及其以后支持使用变量名访问类常数以及 Enum 成员。

class MyClass {
    public const MY_CONST = 42;
}

$constName = 'MY_CONST';

echo MyClass::{$constName};

PHP 8.3 之前,ClassName::{$varName} 语法获取类常量是不允许的,会出现语法错误:

Parse error: syntax error, unexpected token ";", expecting "(" in ... on line ...

Enum 也有同样的限制,不能动态获取 Enum 成员:

enum MyEnum: int {
    case MyMember = 42;
}

$enumName = 'MyMember';

echo MyEnum::{$enumName}->value;
Parse error: syntax error, unexpected token "->", expecting "(" in ``` on line ```

PHP8.3之前,访问类常量和 Enum 成员的唯一方法是 constant() 函数:

echo \constant("MyClass::$constName");
echo \constant("MyEnum::$enumName")->value;

PHP 8.3 之后允许直接动态获取类常量和 Enum 成员。这意味着导致语法错误的两个代码片段在 PHP8.3 和更高版本中的工作效果与预期一致。

  class MyClass {
      public const MY_CONST = 42;
  }

  $constName = 'MY_CONST';

- echo \constant("MyClass::$constName");
+ echo MyClass::{$constName}; 
 enum MyEnum: int {
     case MyMember = 42;
 }

 $enumName = 'MyMember';

- echo \constant("MyEnum::$enumName")->value;
+ echo MyEnum::{$enumName}->value;

{} 内的表达式不限于变量。任何返回字符串的表达式都是可以的:

class MyClass {
    public const MY_CONST = 42;
}

$constPrefix = 'MY_';

echo MyClass::{$constPrefix . 'CONST'};

未定义的常数及 Enum 行为

当尝试访问未定义的类常量或 Enum 成员时,行为没有变化。它们都会导致未定义的常量错误

Fatal error: Uncaught Error: Undefined constant MyEnum::MyMembers in ...:...

::class 魔术常量

::class 魔术常量(返回类/Enum 的全名)也允许使用新语法:

class Foo {}
$constant = 'class';

echo Foo::{$constant}; // "Foo"

类型错误

尝试使用返回值不是字符串的表达式获取类常量或者 Enum 成员,会导致 TypeError 异常。

class Foo {}
$constant = 16;

echo Foo::{$constant};
Fatal error: Uncaught TypeError: Cannot use value of type int as class constant name in ...:...

向下兼容性影响

PHP 8.3 之前,ClassName::{$constantName} 语法不被允许,会导致语法错误。使用该语法的 PHP 应用无法在老版的 PHP 中兼容。