PHP-Äquivalent für einen Python-Dekorator?

Ich möchte in der Lage sein, eine PHP-Funktion um eine andere Funktion zu wickeln, aber ihre ursprüngliche Name / Parameterliste intakt zu lassen.

Zum Beispiel:

function A() { print "inside A()\n"; } function Wrap_A() { print "Calling A()\n"; A(); print "Finished calling A()\n"; } // <--- Do some magic here (effectively "A = Wrap_A") A(); 

Ausgabe:

 Calling A() inside A() Finished calling A() 

4 Solutions collect form web for “PHP-Äquivalent für einen Python-Dekorator?”

Anscheinend könnte Runkit Ihnen helfen .

Auch das kannst du immer so machen. Setzen Sie den ursprünglichen Spaß in einer Klasse, und der Dekorateur in eine erweiterte Klasse. Instantiate und gehen.

Vielleicht suchst du nach call_user_func_array :

 function wrapA() { $args = func_get_args(); return call_user_func_array('A', $args); } 

Seit PHP 5.3 könnte man sogar sagen:

 return call_user_func_array('A', func_get_args()); 

Nachdem du deine Frage bearbeitet hast, würde ich sagen, nein, das ist nicht möglich, aber es gibt einige Möglichkeiten, diese Frage zu sehen: wie man einen Dekorateur in PHP implementiert?

Das kannst du nicht mit Funktionen in PHP machen. In anderen dynamischen Sprachen wie Perl und Ruby können Sie zuvor definierte Funktionen neu definieren, aber PHP wirft einen schwerwiegenden Fehler auf, wenn Sie versuchen, dies zu tun.

In 5.3 können Sie eine anonyme Funktion erstellen und in einer Variablen speichern:

 <?php $my_function = function($args, ...) { ... }; $copy_of_my_function = $my_function; $my_function = function($arg, ...) { /* Do something with the copy */ }; ?> 

Alternativ können Sie das traditionelle Dekorationsmuster und / oder eine Fabrik verwenden und stattdessen mit Klassen arbeiten.

Hier ist meine Methode der Nachahmung von Dekorateuren aus Python in PHP.

 function call_decorator ($decorator, $function, $args, $kwargs) { // Call the decorator and pass the function to it $decorator($function, $args, $kwargs); } function testing ($args, $kwargs) { echo PHP_EOL . 'test 1234' . PHP_EOL; } function wrap_testing ($func, $args, $kwargs) { // Before call on passed function echo 'Before testing'; // Call the passed function $func($args, $kwargs); // After call on passed function echo 'After testing'; } // Run test call_decorator('wrap_testing', 'testing'); 

Ausgabe:

 Before testing testing 1234 After testing 

Mit dieser Implementierung kann man auch so etwas mit einer anonymen Funktion machen:

 // Run new test call_decorator('wrap_testing', function($args, $kwargs) { echo PHP_EOL . 'Hello!' . PHP_EOL; }); 

Ausgabe:

 Before testing Hello! After testing 

Und endlich kannst du auch so etwas machen, wenn du so geneigt bist.

 // Run test call_decorator(function ($func, $args, $kwargs) { echo 'Hello '; $func($args, $kwargs); }, function($args, $kwargs) { echo 'World!'; }); 

Ausgabe:

 Hello World! 

Mit dieser Konstruktion oben können Sie Variablen an die innere Funktion oder den Wrapper übergeben, wenn nötig. Hier ist die Umsetzung mit einer anonymen inneren Funktion:

 $test_val = 'I am accessible!'; call_decorator('wrap_testing', function($args, $kwargs){ echo $args[0]; }, array($test_val)); 

Es wird genau das gleiche ohne eine anonyme Funktion funktionieren:

 function test ($args, $kwargs) { echo $kwargs['test']; } $test_var = 'Hello again!'; call_decorator('wrap_testing', 'test', array(), array('test' => $test_var)); 

Schließlich, wenn Sie die Variable innerhalb entweder der Wrapper oder der Wrappie ändern müssen, müssen Sie nur die Variable durch Verweis übergeben.

Ohne referenz:

 $test_var = 'testing this'; call_decorator(function($func, $args, $kwargs) { $func($args, $kwargs); }, function($args, $kwargs) { $args[0] = 'I changed!'; }, array($test_var)); 

Ausgabe:

 testing this 

Mit Bezug:

 $test_var = 'testing this'; call_decorator(function($func, $args, $kwargs) { $func($args, $kwargs); }, function($args, $kwargs) { $args[0] = 'I changed!'; // Reference the variable here }, array(&$test_var)); 

Ausgabe:

 I changed! 

Das ist alles, was ich jetzt habe, es ist ein ziemlich nützlich in vielen Fällen, und du kannst sie sogar mehrmals umwickeln, wenn du willst.

  • Wrapping einer C-Bibliothek (GSL) in einem Zython-Code durch Rückruf
  • Kann nicht auf Windows-Steuerelemente in pywinautos hwndwrapper (Wrapper-Klasse) zugreifen
  • Custom Wrapper für die Indexierung der Python-Liste ab 1
  • Bringe eine Struktur zu Python von C ++ mit BOOST.python zurück
  • Exposing `defaultdict` als regelmäßiges` dict`
  • Java Wrapper auf Perl / Python Code
  • Zusätzlicher Parameter für Django Modelle
  • General Dekorateur zu wrap versuchen außer in Python?
  • Führen Sie ein MATLAB-Skript aus python + pass args
  • Wie wickle ich einen xmlrpc-Funktionsaufruf ein?
  • Cython cdef Klasse nicht anzeigen doc string oder __init__ Parameter
  • Python ist die beste Programmiersprache der Welt.