Comment exécuter immédiatement une fonction anonyme en PHP?

96

En JavaScript, vous pouvez définir des fonctions anonymes qui sont exécutées immédiatement:

(function () { /* do something */ })()

Pouvez-vous faire quelque chose comme ça en PHP?

Emanuil Rusev
la source
2
Je n'ai pas php 5.3 sur mes mains pour essayer, mais comment call_user_func(function(){/* stuff */})faire?
Jasper

Réponses:

121

Pour PHP7: voir la réponse de Yasuo Ohgaki :(function() {echo 'Hi';})();

Pour les versions précédentes: la seule façon de les exécuter immédiatement à laquelle je pense est

call_user_func(function() { echo 'executed'; });
Gordon
la source
12
À moins que (ou, jusqu'à ce que) le chaînage des appels de fonction ne soit introduit, ce serait également ma suggestion.
salathe
2
@Gordon: php 5.4 toujours rien?
dynamique
@ yes123 non. doivent encore utilisercall_user_func
Gordon
2
@BennettMcElwee disons les choses de cette façon: même si cela fonctionne un peu plus lentement que l'alternative define-assign-call, la probabilité que cela pose un goulot d'étranglement important dans votre application est très faible. en cas de doute, profilez votre application dans des conditions réelles.
Gordon
Merci @Gordon, c'est ce que je pensais. J'ai eu l'impression que salathe et yes123 n'étaient pas satisfaits de cette méthode, et je me suis demandé pourquoi. Cela me semble parfaitement bien.
Bennett McElwee
28

C'est PHP 7de faire de même en javascript

$gen = (function() {
    yield 1;
    yield 2;

    return 3;
})();

foreach ($gen as $val) {
    echo $val, PHP_EOL;
}

echo $gen->getReturn(), PHP_EOL;

La sortie est:

1
2
3
Wallace Maxters
la source
15

Bien sûr, vous pouvez utiliser call_user_func, mais il existe encore une autre alternative assez simple:

<?php
// we simply need to write a simple function called run:
function run($f){
    $f();
}

// and then we can use it like this:
run(function(){
    echo "do something";
});

?>
Pacerier
la source
1
Je veux une fonction qui s'exécute immédiatement, car la fonction que je suis en train de définir en est une qui NE DOIT PAS être appelée plus d'une fois en exécution normale. Le problème avec la définition d'une fonction nommée, run (), comme vous l'avez fait, est que toute autre personne qui voit le code peut penser qu'elle peut également appeler run () dans une autre partie du code. La fonction d'exécution immédiate indique clairement que ce code ne doit pas être exécuté deux fois.
Daniel Howard
3
Ils ne peuvent pas appeler runvotre fonction dans une autre partie du code car il n'y a pas de descripteur de votre fonction existant après la ligne qui l'exécute immédiatement.
Pacerier
3
@DanielHoward Le but de run()est d'exécuter immédiatement la fonction sans nom qui lui est passée. Identique à call_user_func(), aucun paramètre n'est transmis.
Cypher
1
@JordanLev, Il a une implémentation plus simple (juste une ligne :) $f();et pourrait être plus rapide si le moteur que vous utilisez n'optimise pas pour le cas particulier où call_user_funcil n'y a qu'un seul argument de fonction. C'est parce que call_user_funcprend en charge le passage de plusieurs paramètres et que son premier argument prend en charge une chaîne en tant qu'argument ou une fonction. Cela dit, si call_user_funcc'est beaucoup plus lisible, je ne l'utiliserais runque si le code est situé quelque part au bas de la pyramide .
Pacerier
1
@JordanLev, "implémentation plus simple" fait référence à la comparaison entre le code à l' intérieur des fonctions runet call_user_func. call_user_funca un inconvénient inhérent par rapport à runcar runne fait qu'une chose, alors que call_user_funcprend en charge des fonctionnalités supplémentaires en plus de faire ce que runfait. Vous pouvez essayer un test de boucle rapide ( par exemple ) pour voir lequel est le plus rapide sur votre moteur.
Pacerier
11

C'est le plus simple pour PHP 7.0 ou version ultérieure.

php -r '(function() {echo 'Hi';})();'

Cela signifie créer une fermeture, puis l'appeler comme fonction en suivant "()". Fonctionne comme JS grâce à un ordre d'évaluation des variables uniforme.

https://3v4l.org/06EL3

Yasuo Ohgaki
la source
2
Bonne réponse, mais pourquoi le formatez-vous comme une opération de ligne de commande?
Kodos Johnson
6
(new ReflectionFunction(function() {
 // body function
}))->invoke();
intérieur
la source
6
pouvez-vous fournir plus de détails? peut-être ajouter une explication?
MoralCode
2

Notez que la réponse acceptée est correcte mais cela prend 1,41x plus longtemps (41% plus lent) que de déclarer une fonction et de l'appeler sur deux lignes.

[Je sais que ce n'est pas vraiment une nouvelle réponse, mais j'ai pensé qu'il était utile de l'ajouter quelque part pour les visiteurs.]

Détails:

<?php
# Tags: benchmark, call_user_func, anonymous function 
require_once("Benchmark.php");
bench(array(
        'test1_anonfunc_call' => function(){
                $f = function(){
                        $x = 123;
                };
                $f();
        },
        'test2_anonfunc_call_user_func' => function(){
                call_user_func(
                        function(){
                                $x = 123;
                        }
                );
        }
), 10000);
?>

Résultats:

$ php test8.php
test1_anonfunc_call took 0.0081379413604736s (1228812.0001172/s)
test2_anonfunc_call_user_func took 0.011472940444946s (871616.13432805/s)
Pelles
la source
0

Je l'ai essayé de cette façon, mais c'est plus verbeux que la réponse principale en utilisant n'importe quel opérateur (ou fonction) qui vous permet de définir la fonction en premier:

    $value = $hack == ($hack = function(){
            // just a hack way of executing an anonymous function
            return array(0, 1, 2, 3);                
    }) ? $hack() : $hack();
Paul Jérôme Bordallo
la source
2
Alors pourquoi pas simplement $hack = function(){...}; $hack()?
0

Ce n'est pas une réponse directe, mais une solution de contournement. Utilisation de PHP> = 7. Définition d'une classe anonyme avec une méthode nommée et construction de la classe et appel immédiat de la méthode.

$var = (new class() { // Anonymous class
    function cool() { // Named method
        return 'neato';
    }
})->cool(); // Instantiate the anonymous class and call the named method
echo $var; // Echos neato to console.
le nom le plus cool36
la source
-2

Non exécuté immédiatement, mais proche de;)

<?php

$var = (function(){ echo 'do something'; });
$var();

?>
James
la source