2009-07-13 12 views
8

Ich bin heute auf ein interessantes Thema gestoßen. Wir haben eine Anwendung, die die Caching-Funktionalität von Zend Frameworks nutzt. Ein Antrag auf diese Anwendung erfordert typischerweise eine Factory-Methode die folgende Zeilecall_user_func_array vs. call_user_func

$result = call_user_func_array(array("myclass", "factory"), array($id)); 

Die Idee, ein Objekt aus der Factory-Methode zurückzukehren ist, dass wir später zugreifen können. Wenn wir eine Caching-Funktion implementiert haben, stirbt dieser Aufruf einfach. Keine Fehler, nur ein weißer Bildschirm. Nichts im Fehlerprotokoll. Wir können die Zeile vor dem Fehler protokollieren, aber der Fehler in der Factory-Methode versucht nichts.

Interessanterweise die Linie zu ändern:

$result = call_user_func(array("myclass", "factory"), $id); 

behebt das Problem.

Wir haben ein paar Stunden damit verbracht, nach Fehlerberichten Ausschau zu halten und haben uns nicht viel vorgenommen, um dieses Verhalten zu erklären. Gedanken an jemanden?

+0

Ich habe dieses Problem erst kürzlich beim Konvertieren meines gesamten Codes zur Verwendung von Namespaces bemerkt. Die Klasse existiert gut und ich kann Instanzen davon instanziieren. Aber wenn ich eine Instanzen nehme und versuche, eine Methode mit _array oder nicht aufzurufen, passiert nichts. Der Code wird fortgesetzt, aber die Methode scheint nie aufgerufen zu werden. –

Antwort

2

ich Probleme gehabt haben So kam es, dass __autoload nicht ordnungsgemäß zündete, wenn eine nicht-geladene Klasse über einen PHP-Befehl aufgerufen wurde. Keine andere Strategie als dumme Versuch und Irrtum dafür, soweit ich weiß, versuchen Sie einfach, wenn eine Zeile explizit die Klasse aufruft, bevor der PHP-Befehl es für Sie löst.

$dummy = new MyClassName; 
call_user_func_array(array('MyClassName', 'method'), array($id)); 
unset($dummy); 
+0

Meine Theorie besagt, dass call_user_func_array ein wenig rücksichtsloser ist (aus Mangel an einem besseren Begriff), wenn Sie versuchen, den Anruf zu tätigen. Es wäre interessant, die Quelle der beiden Funktionen zu sehen, um sie zu vergleichen. Ich werde einen PHP-Fehlerbericht für dieses Problem einreichen und sehen, was sie sagen. – goose77

+0

Der Aufruf von '__autoload' direkt oder zumindest' class_exists' (mit dem zweiten Parameter true, der die Standardeinstellung ist) wäre eine billigere Möglichkeit, den Autoloader auszulösen. Auf diese Weise verschwenden Sie nicht den Speicher, der eine Instanz der Klasse instanziiert. – jason

0

Welche Version von PHP verwenden Sie? Es gab ein Problem bei der Kombination von call_user_func_array mit ReflectionClass an einem Punkt. Ich bin mir nicht sicher, ob es schon repariert ist.

+0

wir verwenden 5.2.8 – goose77

+0

Ich bin mir ziemlich sicher, dass das Problem, über das ich rede, älter ist. – troelskn

0

Ist es segfauling? Überprüfen Sie Ihre 'root' Apache Logs (außerhalb eines virtuellen Hosts) und sehen Sie, was los ist. Wenn dieser Thread segfauling ist, können Sie dies in den PHP-Mailinglisten und/oder Bug Tracker verfolgen.

Alternativ versuchen Sie könnten http im Single-User-Modus ausgeführt wird, in GDB, mit einem Debug-Kompilierung von PHP und sehen, ob Sie es erfassen kann, aber das ist eine Menge Arbeit :-)

+0

Ich habe alle meine Protokolle durchforstet, und es gibt keine Anzeichen dafür, dass Apache segfaulting ist. Ich wünschte, ich hätte Zeit, Apache im Einzelbenutzermodus zu debuggen. – goose77

+1

Warten Sie ... überprüfen Sie, dass ... es segfault ist. Auf nach PHP gehe ich. – goose77

+0

Ich habe in PHP ein paar schwer zu debuggende Segfaults laufen, wenn ich Autoloading für meine Klassen benutze. Grundsätzlich lösen einige Funktionen den Autoloader nicht aus, wenn eine Klasse nicht existiert, werfen nicht einmal einen fatalen Fehler und fahren mit rücksichtsloser Aufgabe fort. Ein gutes Beispiel ist die Verwendung von method_exists() mit einer Zeichenfolge, die einen Klassennamen darstellt, der noch nicht eingeschlossen wurde == segfault. – jason

Verwandte Themen