Как вызвать метод invoke переменной-члена внутри класса

в PHP 5.4.5, здесь. Я пытаюсь вызвать объект, который хранится как член какого-либо другого объекта. Вот так (очень грубо)

class A {
    function __invoke () { ... }
}

class B {
    private a = new A();
 ...
    $this->a();  <-- runtime error here
}

это приводит к ошибке выполнения, конечно, потому что нет метода, называемого a. Но если я напишу звонок так:

($this->a)();

затем я получаю синтаксическую ошибку.

конечно, я могу написать

$this->a->__invoke();

но это кажется невыносимо уродливым и скорее подрывает точку функторов. Я просто ... интересно, есть ли лучший (или официальный) способ.

3 ответов


есть три способа:

непосредственно __invoke, о котором вы уже упоминали:

$this->a->__invoke();

путем присвоения переменной:

$a = $this->a;
$a();

С помощью call_user_func:

call_user_func($this->a);

последние, вероятно, то, что вы ищете. Оно имеет преимущество что оно работает с любым callable.


Я знаю, что это поздний ответ, но используйте комбинацию __call () в Родительском и __invoke () в подклассе:

class A {
  function __invoke ($msg) {
    print $msg;
  }
}

class B {
    private $a;

    public function __construct() { $this->a = new A(); }

    function __call($name, $args)
    {
      if (property_exists($this, $name))
      {
        $prop = $this->$name;
        if (is_callable($prop))
        {
          return call_user_func_array($prop, $args);
        }
      }
    }
}

тогда вы должны быть в состоянии достичь синтаксического сахара, который вы ищете:

$b = new B();
$b->a("Hello World\n");

FYI в PHP 7 + скобка вокруг обратного вызова внутри объекта теперь работает:

class foo {                                                                     
    public function __construct() {                                             
        $this -> bar = function() {                                             
            echo "bar!" . PHP_EOL;                                              
        };                                                                      
    }                                                                           

    public function __invoke() {                                                
        echo "invoke!" . PHP_EOL;                                               
    }                                                                           
}                                                                               

(new foo)();                                                                    

$f = new foo;                                                                   
($f -> bar)(); 

результат:

invoke!
bar!