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

PHP 8.3:未修改readonly属性却触发无法修改只读属性错误

错误原因分析

你遇到的问题核心在于readonly属性的初始化规则:

  • PHP的readonly属性只能在声明该属性的类的构造函数中被初始化一次,一旦初始化完成,就无法再被修改(包括子类或父类的构造函数都不能再次赋值)。
  • 你的代码中,ImportFactoryAbstract(子类)和XmlLeafListAbstract(父类)都声明了protected readonly AppConfig $appConfig和protected readonly array $list属性。当子类构造函数调用parent::__construct()时,父类构造函数会尝试再次给这些readonly属性赋值,但此时这些属性已经被子类的构造函数初始化过了,违反了readonly属性的不可修改规则,因此触发致命错误。
解决思路与代码修正

最直接的修复方式是移除子类中重复声明的readonly属性,因为父类已经定义了这些属性,子类可以直接继承并使用,不需要重复声明:

修正后的ImportFactoryAbstract类代码:

abstract class ImportFactoryAbstract extends XmlLeafListAbstract
{
    public function __construct(
        AppConfig $appConfig,
        array     $list,
    )
    {
        // do some stuff

        $unhandledXmlElements = [];
        parent::__construct($appConfig, $unhandledXmlElements, $list);

        // do some more stuff
    }
}

补充说明

  • 子类构造函数不再声明protected readonly属性,而是直接将参数传递给父类构造函数,由父类负责初始化readonly属性,这样就避免了重复赋值的问题。
  • 如果子类需要在构造函数中使用这些属性,因为已经继承了父类的属性,直接通过$this->appConfig和$this->list访问即可,无需重新声明。

如果有特殊需求必须在子类中处理这些属性,还可以考虑:

  • 不使用readonly修饰符,改用私有属性+只读getter方法的方式控制属性不可修改。
  • 调整类的继承结构,避免父类和子类重复声明相同的readonly属性。

内容的提问来源于stack exchange,提问作者Andrew Sohn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 13:19:55