Calling closure assigned to object property directly

前端 未结 12 2059
孤街浪徒
孤街浪徒 2020-11-22 14:02

I would like to be able to call a closure that I assign to an object\'s property directly without reassigning the closure to a variable and then calling it. Is this possible

相关标签:
12条回答
  • 2020-11-22 14:42

    I note that this works in PHP5.5

    $a = array();
    $a['callback'] = function() {
        print "HelloWorld!";
    };
    $a['callback']();
    

    Allows one to create a psuedo-object collection of closures.

    0 讨论(0)
  • 2020-11-22 14:44

    You can do this by calling __invoke on the closure, since that's the magic method that objects use to behave like functions:

    $obj = new stdClass();
    $obj->callback = function() {
        print "HelloWorld!";
    };
    $obj->callback->__invoke();
    

    Of course that won't work if the callback is an array or a string (which can also be valid callbacks in PHP) - just for closures and other objects with __invoke behavior.

    0 讨论(0)
  • 2020-11-22 14:44

    well, it should be emphisized that storing the closure in a variable, and call the varible is actually (wierdly) faster, depending on the call amount, it becomes quite a lot, with xdebug (so very precise measuring), we are talking about 1,5 (the factor, by using a varible, instead of directly calling the __invoke. so instead , just store the closure in a varible and call it.

    0 讨论(0)
  • 2020-11-22 14:47

    Updated:

    $obj = new stdClass();
    $obj->callback = function() {
         print "HelloWorld!";
    };
    

    PHP >= 7 :

    ($obj->callback)();
    

    PHP >= 5.4 :

    $callback = $obj->callback;  
    $callback();
    
    0 讨论(0)
  • 2020-11-22 14:49

    It seems to be possible using call_user_func().

    call_user_func($obj->callback);
    

    not elegant, though.... What @Gordon says is probably the only way to go.

    0 讨论(0)
  • 2020-11-22 14:51

    Since PHP 7 a closure can be called using the call() method:

    $obj->callback->call($obj);
    

    Since PHP 7 is possible to execute operations on arbitrary (...) expressions too (as explained by Korikulum):

    ($obj->callback)();
    

    Other common PHP 5 approaches are:

    • using the magic method __invoke() (as explained by Brilliand)

      $obj->callback->__invoke();
      
    • using the call_user_func() function

      call_user_func($obj->callback);
      
    • using an intermediate variable in an expression

      ($_ = $obj->callback) && $_();
      

    Each way has its own pros and cons, but the most radical and definitive solution still remains the one presented by Gordon.

    class stdKlass
    {
        public function __call($method, $arguments)
        {
            // is_callable([$this, $method])
            //   returns always true when __call() is defined.
    
            // is_callable($this->$method)
            //   triggers a "PHP Notice: Undefined property" in case of missing property.
    
            if (isset($this->$method) && is_callable($this->$method)) {
                return call_user_func($this->$method, ...$arguments);
            }
    
            // throw exception
        }
    }
    
    $obj = new stdKlass();
    $obj->callback = function() { print "HelloWorld!"; };
    $obj->callback();
    
    0 讨论(0)
提交回复
热议问题