我有点担心为什么在PHP 7中删除了使用数组元素作为方法名访问对象方法的功能。
E.g:
$carObj = new Car();
$array = ['method'=>'getMilage', 'object'=>$carObj];
// FATAL HERE:
$mileage = $array['object']->$array['method']();
// WORKS OK:
$objName = $array['object'];
$metName = $array['method'];
$mileage = $objName->$metName();
这段代码肯定适用于PHP 5.6,但是当切换到PHP 7.1时它会抛出致命的东西。在发行说明和SO主题中找不到任何相关内容。
P.S。最初在PHP升级时在 Magento 1.14.2.0 版本中找到此内容,因为Varien库使用此代码:
文件:Varien / File / Uploader.php
//run validate callbacks
foreach ($this->_validateCallbacks as $params) {
if (is_object($params['object']) && method_exists($params['object'], $params['method'])) {
$params['object']->$params['method']($this->_file['tmp_name']);
}
}
给出这个:
致命错误:未捕获错误:函数名称必须是字符串 第274行/var/www/html/lib/Varien/File/Uploader.php
-
编辑#1:
您可以在此处测试:
http://sandbox.onlinephpfunctions.com/code/d1d2d36f96a1b66ed7d740db328cd1f14cc2d7d8
答案 0 :(得分:6)
(注意:我假设my
声明在这里应该是'object'=>'carObj'
- 否则此代码无法在任何版本的PHP中运行。)< / p>
线索位于致命错误之前引发的注意:数组到字符串转换...... 通知中。
在PHP 5中,以下语句:
'object'=>$carObj
的评估如下:
$array['object']->$array['method']();
在对象上调用$array['object']->{$array['method']}();
之前对其进行评估。
在PHP 7中,它被评估为
$array['method']
首先在对象上查找($array['object']->$array)['method']();
属性。由于它不存在(显然,因为它是一个数组),抛出通知,然后在无法调用方法本身时发生后续致命错误。
如果要保留PHP 5的行为,请在方法名称查找周围包裹一些$array
:
{}
这里有更详细的解释:http://php.net/manual/en/migration70.incompatible.php
答案 1 :(得分:2)
您的代码肯定不适用于PHP5.6
$array['object']
的内容是一个字符串,并且在字符串上使用->
成员运算符始终会引发错误
在[...] [...]行上的[...]字符串中调用成员函数getMilage()
实现此功能的唯一方法是使用$
解析var或 - 甚至更好地将对象存储在数组中而不仅仅是var。
$mileage = ${$array['object']}->$array['method']();
更好的解决方案
$array = ['method' => 'getMilage', 'object' => $carObj];
$mileage = $array['object']->{$array['method']}();
旁注:在php7中,他们在模糊不清的情况下更改了评估顺序 - 因此您必须在{}
周围明确添加$array['method']
。为了防止这种情况,我们将首先正常提取对象和方法,然后在没有数组解除引用的情况下简单地调用它。
顺便说一下。您发布的Magento Varien代码也希望$params['object']
成为一个数组。甚至还有一个is_object
测试来确保,你不能只传递var名称。
//run validate callbacks - even in php7
foreach ($this->_validateCallbacks as $params) {
if (is_object($params['object']) && method_exists($params['object'], $params['method'])) {
$object = $params['object'];
$method = $params['method'];
$object->$method($this->_file['tmp_name']);
}
}
答案 2 :(得分:0)
您必须在对象变量
之前添加$$carObj = new Car();
$array = ['method'=>'getMilage', 'object'=>'carObj'];
$object = $array['object'];
$method = $array['method'];
// FATAL HERE:
$mileage = $$object->$method();
// WORKS OK:
$objName = $array['object'];
$metName = $array['method'];
$mileage = $$objName->$metName();