Search code examples
phpspecificationsmagic-methods

Cannot use invoke magic method within another object


I have experienced something that I think it's a bug, but I'm not sure. So I come here to ask to the people who know more about this than me, is this a PHP bug? Look at the following lines:

<h1>Tests</h1>

<?php
class Foo
  {
  public function __invoke()
    {
    return 'Called correctly';
    }
  }

class Boo
  {
  public function __construct()
    {
    $this->Foo = new Foo();
    }
  }

$Foo = new Foo();
echo $Foo();

echo "<br><br><hr><br><br>";

$Boo = new Boo();
echo $Boo->Foo();

According to the specification, since The __invoke() method is called when a script tries to call an object as a function, I should obtain this:

Called correctly


Called correctly

But the last echo is not executed. Instead, I get this:

PHP Fatal error: Call to undefined method Boo::Foo() in [...]/index.php on line 26

Is this a bug or an expected behaviour? If it's a bug, some help about how to submit it would be highly appreciated.

EDIT based on Jon answer to show further the ugly behaviour

class Doo
  {
  public function __construct()
    {
    // The Foo class is the same as the one defined before

    $Test = new Foo();
    echo $Test();      // Echos correctly

    echo "<br><br><hr><br><br>";

    $this->Foo = $Test;
    echo $this->Foo();  // Error. Heisenbehaviour?
    }
  }

$Boo = new Doo();

Solution

  • It is not a bug, and it is not limited to Foo being an object that defines __invoke. You would get the same error with any callable:

    class Foo
    {
        private $bar = 'rand';
    
        public function __construct()
        {
            $this->bar(); // won't work
        }  
    }
    

    You need to either write this as two lines, or use call_user_func:

    // #1
    $Boo = new Boo();
    $Foo = $Boo->Foo;
    $Foo();
    
    // #2
    $Boo = new Boo();
    call_user_func($Boo->Foo);