PHP 8.1+中创建只读属性的引用为何触发修改错误?
<?php declare(strict_types=1); class Example { public readonly array $setOne; public readonly array $setTwo; public function __construct() { // Populate $setOne and $setTwo with a lot of data } public function doThing() { $map = [ 'one' => &$this->setOne, 'two' => &$this->setTwo, ]; // Loop over the Map and evaluate the data // Take action on the data, but don't try to change it } }
在PHP >=8.1版本中,尝试创建readonly属性的引用时,会触发错误:Fatal error: Uncaught Error: Cannot modify readonly property。若执行unset($map['one'][0]);这类修改操作触发该错误是合理的,但仅创建引用就报错,请问为何PHP会将创建引用视为修改操作?
原因解析
PHP的readonly属性核心设计目标是确保属性在初始化完成后,无法被重新赋值或间接修改。创建引用的行为之所以被判定为“修改操作”,本质是因为它打破了readonly属性的安全边界:
- 引用直接关联到属性的底层值容器(zval),相当于给readonly属性开了一个不受赋值限制的“后门”。哪怕你当前没打算修改,后续任何通过引用对值的操作(比如重新赋值、修改数组元素)都会直接篡改readonly属性的内容,完全违背readonly的设计初衷。
- PHP采取的是预防性拦截策略:与其等到后续真的发生修改再报错,不如从源头禁止创建引用的行为,彻底杜绝readonly属性被篡改的可能性。
举个简单的例子,如果允许创建引用,后续哪怕误写$map['one'] = [];,就会直接覆盖readonly属性的原有值,这显然不符合readonly属性的定义。PHP选择在创建引用时就触发错误,是为了从根源上消除这种潜在风险。
内容的提问来源于stack exchange,提问作者Tyler V.
相关产品推荐
相关产品推荐

