Im PHP-Handbuch für anonyme Funktionen (dh Closures) heißt es:
Anonyme Funktionen werden derzeit mit der Closure-Klasse implementiert. Dies ist ein Implementierungsdetail und auf sollte nicht Verlass sein .
(Schwerpunkt ist mein eigener)
Ist es möglich, eine Variable so zu testen, dass der Test nur dann true zurückgibt, wenn die Variable eine Closure ist, ohne auf die Closure-Klasse zu verweisen?
Mit anderen Worten, wie kann ich Folgendes so umschreiben, dass es zu einem Fehler kommt, wenn $bar
alles andere als eine anonyme Funktion ist:
BEARBEITEN: Basierend auf den Antworten erhalten Sie hier einen Beispieltest.
Anmerkungen:
ReflectionFunction::isClosure()
scheint fast nutzlos zu sein: Zu der Zeit, als Sie die erforderlichen Überprüfungen durchgeführt haben, um sicherzustellen, dass ReflectionFunction tatsächlich instanziiert werden kann (außer einer Closure keine Klasse) , Sie haben alle anderen Optionen eliminiert. Code:
%Vor%Testfall:
%Vor%-
Sie können auch
verwenden ReflectionFunctionAbstract::isClosure
- Prüft, ob es geschlossen wurde
Beispiel:
%Vor% Beachten Sie, dass das obige nur TRUE
für PHP 5.3 Lambdas und Closures zurückgibt. Wenn Sie nur wissen möchten, ob ein Argument als Callback verwendet werden kann, wird is_callable
besser funktionieren.
BEARBEITEN Wenn Sie auch Funktoren hinzufügen möchten, können Sie ( ab PHP 5.3.3 )
%Vor%oder
%Vor%wobei letzteres die schnellere Alternative ist.
Eine Closure
-Instanz ist im Grunde genommen nur eine Klasse, die eine __invoke
-Funktion hat, die Sie dem Methodenkörper im laufenden Betrieb zugeführt haben. Aber da dies ein Implementierungsdetail testet, würde ich sagen, es ist so unzuverlässig wie das Testen des Closure
-Klassennamens.
BEARBEITEN Da Sie erwähnen, dass Sie nicht zuverlässig über die Reflection-API testen können, weil beim Übergeben eines Functors an ReflectionFunctionAbstract::isClosure
ein Fehler auftritt, versuchen Sie, die folgende Lösung Ihren Anforderungen anzupassen:
Dies überprüft, ob das übergebene Argument aufrufbar ist. Das $name
Argument speichert den aufrufbaren Namen. Für Schließungen ist dies zur Zeit Closure::__invoke
. Da dies für alle Closures / Lambdas dasselbe sein wird, können wir den Namen des übergebenen Arguments mit einem beliebigen anderen Closure / Lambda vergleichen. Wenn sie gleich sind, muss das Argument ein Closure / Lambda sein. Das Ermitteln des aufrufbaren Namens zur Laufzeit hat den zusätzlichen Vorteil, dass Sie keine Annahmen über die Implementierungsdetails in Ihren Quellcode fest codieren müssen. Wenn Sie einen Funktor übergeben, wird FALSE
zurückgegeben, da er nicht denselben aufrufbaren Namen hat. Da dies nicht auf der Reflection-API beruht, ist es wahrscheinlich auch etwas schneller.
Das obige könnte eleganter als
geschrieben werden %Vor% is_callable
und !is_array
könnten Ihnen dabei helfen. Beachten Sie, dass Sie sich nicht darauf verlassen können, dass der Typhinweis von PHP auf diese Weise angezeigt wird, da Sie die Variable innerhalb der Funktion überprüfen und etwas, z. ein InvalidArgumentException
selbst.