编程

属性钩子在 PHP 8.4 中越来越接近现实

413 2024-05-14 00:50:00

属性钩子(Property Hooks)的 RFC 通过了一个重要的里程碑,获得了压倒性的 34 张赞成票和 1 张反对票。这远远高于通过所需的 ⅔ 多数票。

PHP 中的属性钩子是什么?

以下是 RFC 的提案摘要:

开发人员经常使用方法来包装和保护对对象属性的访问。对于这种逻辑,有几种非常常见的模式,在实践中,重复实现这些模式可能很繁琐。或者,开发人员可以使用 __get__set 来拦截一般的读写操作,但这是一种无条件拦截所有未定义(和一些已定义)属性的大锤方法。属性钩子为常见的属性交互提供了一个更有针对性、专门构建的工具。
这个 RFC 引入了两个“钩子”来覆盖属性的默认 “get” 和 “set” 行为。虽然没有包含在这个初始版本中,但该设计包括在未来支持更多钩子的能力。

属性挂钩的灵感来自 Kotlin、C# 和 Swift 等语言,语法包括两种类似于短闭包和多行闭包的语法变体:

class User implements Named
{
    private bool $isModified = false;
 
    public function __construct(
        private string $first,
        private string $last
    ) {}
 
    public string $fullName {
        // Override the "read" action with arbitrary logic.
        get => $this->first . " " . $this->last;
 
        // Override the "write" action with arbitrary logic.
        set {
            [$this->first, $this->last] = explode(' ', $value, 2);
            $this->isModified = true;
        }
    }
}

该语法不要求两个钩子都要一起定义;以下是该 RFC 中只定义 set 的示例:

class User
{
    public string $name {
        set {
            if (strlen($value) === 0) {
                throw new ValueError("Name must be non-empty");
            }
            $this->name = $value;
        }
    }
 
    public function __construct(string $name) {
        $this->name = $name;
    }
}

可以在 RFC中阅读有关 PHP 中属性钩子的所有详细信息。这个特性在 PHP 8.4 中可能会落地。如果想了解此功能的讨论和进展情况,那么该实现已经是一个 PR 草案。