编程

PHP 8.4:#[Deprecated] 注解

76 2025-02-16 08:29:00

PHP 8.4 引入了一个 名为 #[Deprecated] 的新注解,它可以用于标记 PHP 函数、类方法或类常量为已弃用。

当使用带有 #[Deprecated] 属性的已弃用函数、类或方法时,PHP 会自动发出弃用消息。每次调用该函数/方法/常量时都会触发这条消息。

在引入此属性之前,通常通过使用 trigger_error 函数发出弃用消息和/或在 /** @deprecated */ PHP 文档注释中标记这些信息来发布用户自定义 PHP 函数/方法/常量的弃用。

这种方法并不完美,因为反射 API,特别是 ReflectionFunctionAbstract::isDeprecated() 方法,并不会返回带有 @deprecated PHP 文档注释的弃用状态。有了新的 #[Deprecated] 属性,如果一个 PHP 符号被弃用,则 isDeprecated 方法会在存在该属性时返回 true

带有 #[Deprecated] 属性的函数示例:

#[Deprecated]
function my_deprecated_function(): void {
    echo "Called";
}

my_deprecated_function();
Deprecated: Function my_deprecated_function() is deprecated in ... on line ...
Called

带有 #[Deprecated] 属性的类方法示例:

class Test {
    #[Deprecated]
    public function myMethod(): void {}
}

new Test()->myMethod();
Deprecated: Method Test::myMethod() is deprecated in ... on line ...

带有 #[Deprecated] 属性的类常量示例:

class Test {
    #[Deprecated]
    public const int TEST = 42;
}

echo Test::TEST;
Deprecated: Constant Test::TEST is deprecated in ... on line ...
42

带有 #[Deprecated] 属性的枚举成员示例:

enum MyEnum {
    #[Deprecated]
    case Test;
}

echo MyEnum::Test->name;
Deprecated: Enum case MyEnum::Test is deprecated in ... on line ...
Test

#[Deprecated] 属性适用的目标

#[Deprecated] 属性可以添加到以下目标:

  • 函数
  • 类方法
  • 类常量
  • 枚举成员
  • 常量(自 PHP 8.5 起)

值得注意的是,#[Deprecated] 属性不能用于:

  • 类声明
  • 函数和方法参数

#[Deprecated] 属性概述

#[Attribute(Attribute::TARGET_METHOD|Attribute::TARGET_FUNCTION|Attribute::TARGET_CLASS_CONSTANT)]
final class Deprecated
{
    public readonly ?string $message;
    public readonly ?string $since;

    public function __construct(?string $message = null, ?string $since = null) {}
}

Deprecated 属性类声明在全局命名空间中。应用该属性时,也可以使用完全限定的类名:#[\Deprecated]

指定自定义弃用消息

默认情况下,当 PHP 符号带有 #[Deprecated] 属性时,它会发出一条 %s is deprecated 的弃用消息。

但是,可以使用 #[Deprecated] 属性支持的两个可选参数来自定义此消息。

带有 $message 参数的示例:

#[Deprecated("use bar instead")]
function foo(): void {}

foo();
Deprecated: Function foo() is deprecated, use bar instead in ... on line ...

带有 $message$since 参数的示例:

#[Deprecated('use bar instead', 'v42.16.15')]
function foo(): void {}

foo();
Deprecated: Function foo() is deprecated since v42.16.15, use bar instead in ... on line ...

带有 $message$since 命名参数的示例:

#[Deprecated(message: 'use bar instead', since: 'v42.16.15')]
function foo(): void {}

foo();
Deprecated: Function foo() is deprecated since v42.16.15, use bar instead in ... on line ...

仅带有 $since 参数的示例:

#[Deprecated(since: 'v42.16.15')]
function foo(): void {}

foo();
Deprecated: Function foo() is deprecated since v42.16.15 in ... on line ...

反射函数变更

这一新增 #[Deprecated] 注解不引入任何反射 API 变更。不过,反射 API 现在现在可以使用该属性返回用户空间 PHP 符号的弃用状态:

#[Deprecated]
function my_deprecated_function(): void {}
$reflector = new ReflectionFunction('my_deprecated_function');
$reflector->isDeprecated(); // true

此更改对类方法(ReflectionMethod::isDeprecated) 和类常量/枚举成员(ReflectionClassConstant::isDeprecated()) 也有效。请注意, ReflectionClassConstant 类是 PHP 8.4 中的新类。

替代现有的弃用机制

运行 PHP 8.4 以上版本的应用可以使用新增的 #[Deprecated] 属性安全地为用户空间 PHP 函数和类替换弃用机制:

+ #[Deprecated('use bar instead', 'v42.16.15')]
  function foo(): void {  
-   trigger_error('Function foo() is deprecated since v42.16.15, use bar instead', E_USER_DEPRECATED);  
  }  

向后兼容性影响

除非用户空间 PHP 应用在全局命名空间中声明了名为 Deprecated 的类,否则该变更不会造成任何向后兼容性影响。 

任何使用 #[Deprecated] 属性注解的 PHP 符号将继续在旧版 PHP 中工作,只是不会触发弃用消息

为了在 PHP 8.4+ 和更早的 PHP 版本上持续发出弃用消息,应用必须在函数或类方法本身中发出弃用通知。

#[Deprecated('use bar instead', 'v42.16.15')]
function foo(): void {
    if (\PHP_VERSION_ID < 80400) {
        trigger_error('Function foo() is deprecated since v42.16.15, use bar instead', E_USER_DEPRECATED);
    }
}