I am a bit stuck with question why in PHP 7 dropped functionality of accesing object methods using array elements as method name.
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();
This code works on PHP 5.6 for sure, however when switched to PHP 7.1 it throws now fatal. Failed to find anything re this in release notes and SO topics.
P.S. Originally found this in Magento 1.14.2.0 version upon PHP upgrade, as Varien library uses this code:
File: 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']);
}
}
Gives this:
Fatal error: Uncaught Error: Function name must be a string in
/var/www/html/lib/Varien/File/Uploader.php on line 274
—
EDIT #1:
You can TEST it here:
http://sandbox.onlinephpfunctions.com/code/d1d2d36f96a1b66ed7d740db328cd1f14cc2d7d8
3
Answers
You must add $ before the object variable
Your code works for sure not in PHP5.6
The content of
$array['object']
is an string and using the->
member operator on an string always throws an errorThe only way to get this to work is resolve the var with
$
or – even better store the object inside the array and not simply the var.better solution
Sidenote: in php7 they changed the evaluation order in case of ambiguities – so you have to add explicitly
{}
around$array['method']
. To prevent this, one would normaly extract first the object and method and then simply call it without the array dereferencing.Btw. the Magento Varien code you posted also expects
$params['object']
to be an array. There is even ais_object
test to ensure, you couldn’t pass just var names.(Note: I’m assuming the
'object'=>'carObj'
declaration is supposed to be'object'=>$carObj
here – there’s no way this code works in any version of PHP otherwise.)The clue is in the Notice: Array to string conversion in… notice raised before the fatal error.
In PHP 5, the following statement:
is evaluated like this:
where
$array['method']
is evaluated before calling it on the object.In PHP 7, it’s evaluated like this
where the
$array
property is looked up on the object first. Since it doesn’t exist (obviously, since it’s an array), a notice is thrown, and then a subsequent fatal error when the method itself can’t be called.If you want to preserve the PHP 5 behaviour, wrap some
{}
around the method name lookup:See https://3v4l.org/Is5lX
This is explained in a bit more detail here: http://php.net/manual/en/migration70.incompatible.php