PHP 7将对象方法作为数组元素执行

时间:2018-04-18 10:22:08

标签: php arrays magento php-7

我有点担心为什么在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

3 个答案:

答案 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

{}

请参阅https://3v4l.org/Is5lX

这里有更详细的解释: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();