Question

Je veux pouvoir envelopper une fonction PHP avec une autre fonction, tout en laissant sa liste de noms / paramètres d'origine intacte.

Par exemple:

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

Sortie:

Calling A()
inside A()
Finished calling A()
Était-ce utile?

La solution

Apparemment, runkit pourrait vous aider .

En outre, vous pouvez toujours le faire de la manière OO. Mettez le plaisir original dans une classe et le décorateur dans une classe élargie. Instanciez et partez.

Autres conseils

Voici ma méthode pour imiter les décorateurs de python en 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');

Sortie:

Before testing
testing 1234
After testing

Avec cette implémentation, vous pouvez également faire quelque chose comme ceci avec une fonction anonyme:

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

Sortie:

Before testing
Hello!
After testing

Enfin, vous pouvez même faire quelque chose comme ceci, si vous êtes si enclin.

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

Sortie:

Hello World!

Avec la construction ci-dessus, vous pouvez passer des variables à la fonction interne ou au wrapper, si besoin est. Voici cette implémentation avec une fonction interne anonyme:

$test_val = 'I am accessible!';

call_decorator('wrap_testing', function($args, $kwargs){
    echo $args[0];
}, array($test_val));

Cela fonctionnera exactement de la même manière sans fonction anonyme:

function test ($args, $kwargs) {
    echo $kwargs['test'];
}

$test_var = 'Hello again!';

call_decorator('wrap_testing', 'test', array(), array('test' => $test_var));

Enfin, si vous devez modifier la variable à l'intérieur du wrapper ou du wrappie, il vous suffit de passer la variable par référence.

Sans référence:

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

Sortie:

testing this

Avec référence:

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

Sortie:

I changed!

C’est tout ce que j’ai pour le moment, c’est un outil très utile dans de nombreux cas, et vous pouvez même les envelopper plusieurs fois si vous le souhaitez.

Peut-être recherchez-vous call_user_func_array :

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

depuis PHP 5.3, vous pouvez même dire:

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

après avoir modifié votre question, je dirais que non, ce n'est pas possible, mais il existe quelques moyens. Voir la question suivante: comment implémenter un décorateur en PHP?

Vous ne pouvez pas faire cela avec des fonctions en PHP. Dans d'autres langages dynamiques, tels que Perl et Ruby, vous pouvez redéfinir des fonctions précédemment définies, mais PHP génère une erreur fatale lorsque vous tentez de le faire.

Dans la version 5.3, vous pouvez créer une fonction anonyme et stocker dans une variable:

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

Vous pouvez également utiliser le motif de décorateur traditionnel et / ou une usine et utiliser des classes à la place.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top