首页 > 解决方案 > 为什么 PHP 在 unset() 声明类型属性后调用 __set()?

问题描述

(编辑了这个问题,旧版本引用了RFC的错误版本。)

PHP 中类型化属性的RFC说“如果类型化属性是unset(),那么它将返回到未初始化状态。” 但是,在 PHP 7.4(至少到 7.4.5)中,当类实现时__set(),它的行为确实有所不同,因此它与(原始)未初始化状态不完全相同。第一次设置未初始化的属性时不会调用魔术函数,但在取消设置后再次设置属性时会(意外地)调用它。示例代码

<?php

class X {
    public int $y;
    public function __set($name, $value) {
        echo "__set($name, $value) called";
        $this->$name = $value;
    }
}

$x = new X();
$x->y = 42; // Prints nothing, as expected.
unset($x->y);
$x->y = 43; // Prints `__set(y, 43) called`.

我忽略了什么吗?这是 PHP 当前如何unset()为类型化属性实现的错误吗?或者__set()甚至应该在第一次设置未初始化的类型属性时调用?

标签: phpphp-7.4

解决方案


为什么?

出于惰性初始化模式的目的。

如果一个类型化的属性是 unset(),那么它返回到未初始化的状态。虽然我们很乐意删除对取消设置属性的支持,但此功能目前被 Doctrine 用于延迟初始化

因此,在 PHP 8 中,他们可能会在为延迟初始化提供一些替代机制之后禁止取消设置已声明的属性。


推荐阅读