[注意:我在起草问题,但我想我会继续发布它参考,因为我对发布的警告进行了广泛的搜索没有提供解决方案,我认为这可能会帮助未来。]
我有一个类Thing
,它具有属性$subthing_1
、$subthing_2
、$subthing_3
,所有这些都是对象:
class Thing {
...
public $subthing_1; // object of type Subthing
public $subthing_2; // object of type Subthing
public $subthing_3; // object of type Subthing
...
}
如果我想在Thing的一个例子中得到一个特定的细微之处,我可以这样做:
$thing->subthing_1
这很好地传达了微妙的含义。但我想概括调用了哪种字幕,所以我有一个例程,它可以获取特定字幕的名称,"字幕_1"、"字幕_2"或"字幕_3",并将其存储在数组元素的字符串中。因此,例如,$subthings[4]
具有字符串值"subthing_1"和
$thing->$subthings[4]
应与CCD_ 8完全相同。
如果我做
var_dump($subthings[4]);
结果是
string(10) "subthing_1"
和
var_dump($thing);
结果是
object(Thing)#4 (87) {
...
["subthing_1"]=>
object(Category)#59 (12) {
...
}
...
}
这一切都很好。然而,当我尝试这样做时:
var_dump($thing->$subthings[4]);
我得到这个:
警告:数组到字符串的转换。。。
警告:未定义的属性:Thing::$Array。。。
警告:正在尝试访问类型为null的值的数组偏移量。。。
这让我困惑了很长一段时间,因为我看不清在哪里将数组转换为字符串。$subthings[4]
显然是一个字符串,如var_dump($subthings[4])
所示,而不是一个数组。
这些警告出现在PHP 8.1中,适用于在PHP 5.5中运行良好的代码。
最后,我推断这两个PHP版本之间一定有语法解释的变化。
而在PHP 5.5中,$thing->$subthings[4]
被解释为$thing->{$subthings[4]}
,而在PHP 8.1中$thing->$subthings[4]
被解释为{$thing->$subthings}[4]
。
我到处搜索这一变化的文档,但我想我没有找到正确的关键词。我希望这里有人能提供一个答案,说明这一变化记录在哪里。
解决方案是用大括号包围数组,以强制执行预期的(以前也是默认的(解析顺序:
$thing->{$subthings[4]}
正如Don’t Panic所指出的,此评估语法更改记录在此处:https://www.php.net/manual/en/migration70.incompatible.php#migration70.incompatible.variable-处理间接