2010-06-24 3 views
6

Ich habe einige Tests (um alten Code zu ersetzen) mit der __invoice Magic-Methode gemacht und ich bin mir nicht sicher, ob das ein Bug ist oder nicht:PHP5.3: "Aufruf zu undefinierter Methode" Fehler beim Aufrufen von Aufruf von Klassenvariable

Lets Angenommen, wir haben eine Klasse:

class Calc { 
    function __invoke($a,$b){ 
     return $a*$b; 
    } 
} 

Das folgende ist möglich und funktioniert ohne Probleme:

$c = new Calc; 
$k = $c; 
echo $k(4,5); //outputs 20 

Allerdings, wenn ich eine andere Klasse haben wollen eine Instanz dieses Objekt zu speichern, , Hat dies nicht:

class Test { 
    public $k; 
    function __construct() { 
     $c = new Calc; 
     $this->k = $c; //Just to show a similar situation than before 
     // $this-k = new Calc; produces the same error. 
    } 
} 

Der Fehler tritt auf, wenn wir versuchen, es zu nennen mag:

$t = new Test; 
echo $t->k(4,5); //Error: Call to undefined method Test::k() 

Ich weiß, dass eine „Lösung“ eine Funktion innerhalb der Klasse Test haben könnte (benannt k), um den Anruf mit call_user_func_array "weiterzuleiten", aber das ist nicht elegant.

Ich muss diese Instanz innerhalb einer gemeinsamen Klasse (für Design-Zwecke) behalten und in der Lage sein, sie als Funktion von anderen Klassen zu nennen ... irgendeinen Vorschlag?

Update:

ich etwas interessantes (zumindest für meine Zwecke) gefunden:

Wenn wir die "Klassenvariable" in einer lokalen Variablen zuweisen funktioniert es:

$t = new Test; 
$m = $t->k; 
echo $m(4,5); 
+0

Bitte geben Sie ein vollständiges Codebeispiel an, das Ihr Problem zeigt. Das von Ihnen angegebene Codebeispiel funktioniert nicht und das von Ihnen angegebene Codebeispiel verursacht ein Problem. – Sjoerd

+0

Ja, tut mir leid, mein Schlechter ... Ich aktualisiere es. Sjoerd: Hat dieses Beispiel für dich funktioniert? komisch: S – lepe

Antwort

5

Wenn Sie Do $test->k(), PHP denkt, dass Sie eine Methode auf der $test Instanz aufrufen. Da es keine Methode namens k() gibt, löst PHP eine Ausnahme aus. Was Sie versuchen, ist, dass PHP die öffentliche Eigenschaft k zurückgibt und diese aufruft, aber Sie müssen zuerst k einer Variablen zuweisen. Es ist eine Frage der Dereferenzierung.

Sie konnten die Magie __call Methode, um Ihre Test Klasse hinzufügen zu überprüfen, ob es eine Eigenschaft, mit der aufgerufenen Methode Name ist, und rufen, dass stattdessen aber:

public function __call($method, $args) { 
    if(property_exists($this, $method)) { 
     $prop = $this->$method; 
     return $prop(); 
    } 
} 

Ich lasse die Argumente für den Aufruf an Sie hinzufügen . Sie können auch überprüfen, ob die Eigenschaft is_callable.

Aber wie auch immer, dann kann man tun

$test->k(); 
+0

Wir haben zur selben Zeit gepostet ... Ja vielleicht könnte das helfen ... Wenn ich keine andere bessere Alternative finde, werde ich deine Antwort als gut bezeichnen. – lepe

6

PHP denkt, dass Sie eine Methode k auf Instanz $ t anrufen möchten, wenn Sie tun:

$t->k(4, 5) 

, die durchaus sinnvoll ist. Sie können eine Zwischengröße, um das Objekt zu nennen:

$b = $t->k; 
$b(4, 5); 

Siehe auch bug #50029, das Ihr Problem beschreibt.

+0

+1 zum Finden des Fehlers – Gordon

+0

(+1). Jetzt wird es klar für mich. Danke für den Link. – lepe

2

Sie können Methodensyntax (wie $ foo-> bar()) nicht verwenden, um Closures oder Objekte mit __invoke aufzurufen, da die Engine dies immer als Methodenaufruf betrachtet. Sie könnten es über __call simulieren:

aber es würde nicht so funktionieren wie es ist.