2012-09-26 19 views
8

PHP 5.4.5 hier auf. Ich versuche, ein Objekt aufzurufen, das als Mitglied eines anderen Objekts gespeichert ist. So (sehr grob)So rufen Sie die __invoke-Methode einer Membervariablen innerhalb einer Klasse

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

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

Dies erzeugt natürlich einen Laufzeitfehler, weil es keine Methode namens a gibt. Aber wenn ich den Anruf so schreibe:

($this->a)(); 

dann bekomme ich einen Syntaxfehler.

Natürlich kann ich

$this->a->__invoke(); 

schreiben, aber das scheint unerträglich hässlich, und eher untergräbt den Punkt functors. Ich habe mich nur gefragt, ob es einen besseren (oder offiziellen) Weg gibt.

Antwort

8

ist es drei Möglichkeiten:

Direkt __invoke Aufruf, die Sie bereits erwähnt:

$this->a->__invoke(); 

von einer Variablen zugewiesen:

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

Durch die Verwendung von call_user_func:

call_user_func($this->a); 

Die letzte ist wahrscheinlich, was Sie suchen. Es hat den Vorteil, dass es mit allen abrufbaren funktioniert.

+1

Dank Igor. Von den drei scheint die Zuordnung zur Variablen am klarsten zu sein, aber keine von ihnen ist sehr nett. Versteht jemand, warum die 'offensichtliche' Syntax $ this-> a() die __invoke-Methode des Members nicht finden kann - warum unterscheidet sich der Member-Zugriff grundlegend von der nackten Variablensyntax? –

+1

Weil es mehrdeutig ist. '$ this-> a()' könnte entweder die Methode 'a' oder das Element' $ a' sein. In PHP sind diese beiden stark voneinander getrennt (im Gegensatz zu JS zum Beispiel). – igorw

+0

Ah. Das macht Sinn. Vielen Dank. –

3

Ich weiß, das ist eine späte Antwort, aber eine Kombination aus __call() verwenden, in der Eltern und __invoke() in der Unterklasse:

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); 
     } 
     } 
    } 
} 

Dann sollten Sie in der Lage sein, den syntaktischen Zucker erreichen Sie sind suche:

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

Das ist ein ziemlich gepflegter Ansatz. Vielen Dank. –

2

FYI in PHP 7+ Klammern um einen Rückruf in einem Objekt arbeitet jetzt:

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)(); 

Ergebnis:

invoke! 
bar!