You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP 8.4不对称可见性:带存取器的属性赋值为何未报错?

为什么PHP 8.4中带存取器的public private(set)属性允许外部赋值?

你遇到的差异是因为PHP 8.4对「带存取器的属性」和「无存取器的属性」处理private(set)修饰符的逻辑完全不同:

1. 无存取器的场景(第二个示例)

public private(set) string $phone;是PHP 8.4专门为无存取器属性设计的语法,直接给属性的读、写操作分别指定可见性:

  • 读操作($foo->phone)权限为public,外部可以正常读取;
  • 写操作($foo->phone = ...)权限为private,外部直接赋值会触发可见性检查,抛出Cannot access private property PrefixStyle::$phone错误,这符合预期。

2. 带存取器的场景(第一个示例)

当你为属性显式定义get/set存取器时,属性上的private(set)修饰符会被PHP忽略——此时存取器的可见性需要直接在存取器方法前声明。

你的代码里没有给set存取器添加private修饰,所以set存取器默认继承了属性的public可见性。外部执行$foo->phone = ...时,本质是调用了public权限的set存取器,自然不会触发权限错误,赋值就能成功。

正确的写法:让带存取器的属性仅允许内部赋值

如果要让带存取器的属性的写操作限制在类内部,需要把private修饰符直接加在set存取器前面:

class PrefixStyle
{
    public string $phone {
        get {
            return $this->phone;
        }
        private set {
            $this->phone = $value;
        }
    }
}

此时外部执行赋值操作会触发权限错误,和无存取器场景的行为一致。

另外补充:你第一个示例里的set存取器代码$this->phone = $value没有触发无限递归,是因为PHP 8.4的存取器设计了特殊逻辑——在存取器内部直接访问属性本身时,会跳过存取器逻辑,直接操作底层存储,避免递归调用。

内容的提问来源于stack exchange,提问作者Nitram Nekonečný

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 06:04:58