Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP Callable Object as Object Member

I have a class Logger which, among other things has a method Log.
As Log is the most common use of the Logger instance, I have wired __invoke to call Log

Another class, "Site" contains a member "Log", an instance of Logger.

Why would this work:

$Log = $this->Log;  
$Log("Message");  

But not this:

$this->Log("Message");

The former fails with "PHP Fatal error: Call to undefined method Site::Log()"
Is this a limitation of the callable object implementation, or am I misunderstanding something?

like image 959
James Maroney Avatar asked Nov 01 '09 02:11

James Maroney


3 Answers

Unfortunately, this is (still) a limitation of PHP, but it makes sense when you think about it, as a class can contain properties and methods that share names. For example:

<?php
class Test {
    public $log;

    public function __construct() {
        $this->log = function() {
            echo 'In Test::log property';
        };
    }

    public function log() {
        echo 'In Test::log() method';
    }
}

$test = new Test;
$test->log(); // In Test::log() method
call_user_func($test->log); // In Test::log property
?>

If PHP were to allow the syntax you desire, which function would be invoked? Unfortunately, that only leaves us with call_user_func[_array]() (or copying $this->log to another variable and invoking that).

However, it would be nice if the following syntax was acceptable:

<?php
{$test->log}();
?>

But alas, it is not.

like image 129
rintaun Avatar answered Oct 04 '22 15:10

rintaun


Same reasons you can't do this:

$value = $this->getArray()["key"];

or even this

$value = getArray()["key"];

Because PHP syntax doesn't do short hand very well.

like image 37
Kendall Hopkins Avatar answered Oct 04 '22 15:10

Kendall Hopkins


This may work:

${this->Log}("Message");

But perhaps it's just easier and better to use the full call? There doesn't seem to be a way to get what you want to work on the one line.

The error in your question indicates it is looking for a function defined on the class which doesn't exist. An invokable object isn't a function, and it seems it can't be treated as one in this case.

like image 23
Matthew Scharley Avatar answered Oct 04 '22 15:10

Matthew Scharley