PHP7 method_exists Uncaught Error: Function name must be a string

14,563

This is due to incompatible changes in the order-of-evaluation for processing indirect variables and methods:

Changes to the handling of indirect variables, properties, and methods

Indirect access to variables, properties, and methods will now be evaluated strictly in left-to-right order, as opposed to the previous mix of special cases. The table below shows how the order of evaluaiton has changed.

No, you don't have to change this line:

$item['function']($item, $default);

Because there is no special evaluation going on here, it will just use the array element as function name and call the function. You could change it, and the code will still work properly, but it isn't necessary.

But as you already did correctly you have to change:

$this->$item['function']($item, $default);

to:

$this->{$item['function']}($item, $default);
       ↑                 ↑

Since as you can see in this table:

                    Old and new evaluation of indirect expressions
      Expression            PHP 5 interpretation         PHP 7 interpretation
-------------------------------------------------------------------------------
  $$foo['bar']['baz'] |     ${$foo['bar']['baz']}  |    ($$foo)['bar']['baz']
  $foo->$bar['baz']   |     $foo->{$bar['baz']}    |    ($foo->$bar)['baz']
  $foo->$bar['baz']() |     $foo->{$bar['baz']}()  |    ($foo->$bar)['baz']()
  Foo::$bar['baz']()  |     Foo::{$bar['baz']}()   |    (Foo::$bar)['baz']()

PHP 7 will assume you first want to access an object property, and then you want to access an index from that property, and use its value as method name to call a method (left-to-right order).

To use the variable and index as property name, you have to use curly braces to indicate that.

Share:
14,563
backups
Author by

backups

Updated on June 15, 2022

Comments

  • backups
    backups almost 2 years

    I am getting this error:

    Fatal error: Uncaught Error: Function name must be a string in

    For this code:

    if (function_exists($item['function'])) {
        $item['function']($item, $default);
    } elseif (method_exists($this, $item['function'])) {
        $this->$item['function']($item, $default);
    }
    

    I know that changing the code to

    if (function_exists($item['function'])) {
        $item['function']($item, $default);
    } elseif (method_exists($this,$item['function'])) {
        $this->{$item['function']}($item, $default);
    }
    

    Solved that error, but my question is, should this line

     $item['function']($item, $default);
    

    also be converted to

    {$item['function']}($item, $default);
    

    or can it be left as is?

  • Svetoslav
    Svetoslav over 8 years
    In older PHP version yes, but in 7 its not required for sure.