Accepter la fonction comme paramètre en PHP

104

Je me suis demandé s'il était possible ou non de passer une fonction en paramètre en PHP; Je veux quelque chose comme lorsque vous programmez en JS:

object.exampleMethod(function(){
    // some stuff to execute
});

Ce que je veux, c'est exécuter cette fonction quelque part dans exampleMethod. Est-ce possible en PHP?

Cristian
la source

Réponses:

150

C'est possible si vous utilisez PHP 5.3.0 ou supérieur.

Voir Fonctions anonymes dans le manuel.

Dans votre cas, vous définiriez exampleMethodcomme ceci:

function exampleMethod($anonFunc) {
    //execute anonymous function
    $anonFunc();
}
zombat
la source
9
Merde, je savais que c'était possible. J'allais répondre, mais je voulais trouver de la documentation vers laquelle établir un lien en premier, et je ne savais pas comment cela s'appelait exactement. Eh bien, maintenant je saurai quand je devrai faire ça aussi. Merci.
Rob
3
Avant 5.3, vous pouvez utilisercreate_function
Gordon
Merci beaucoup. Puisque je dois le faire pour PHP4.3, je suppose que je vais devoir faire ce que je veux en utilisant une autre logique.
Cristian
1
@Casidiablo - Voir la réponse de Jage, vous pourrez peut-être faire quelque chose avec create_function(). Ce n'est pas tout à fait la même chose, car vous devez passer votre fonction sous forme de chaîne de code, qui se retrouve ensuite eval()dans les coulisses. Pas idéal, mais vous pourrez peut-être l'utiliser.
zombat
1
Comment l'appellerais-tu? Pouvez-vous donner un nom à la fonction existante? Ex:exampleMethod(strpos);
sumid
51

Juste pour ajouter aux autres, vous pouvez passer un nom de fonction:

function someFunc($a)
{
    echo $a;
}

function callFunc($name)
{
    $name('funky!');
}

callFunc('someFunc');

Cela fonctionnera en PHP4.

webbiedave
la source
17

Vous pouvez également utiliser create_function pour créer une fonction en tant que variable et la transmettre. Cependant, j'aime mieux le sentiment des fonctions anonymes . Allez zombat.

Jage
la source
+1 pour l'alternative. Il semble que l'OP pourrait en avoir besoin.
zombat
Merci! Je dois m'en tenir à une ancienne installation PHP 5.2 et les fonctions anonymoys ne fonctionnent pas là-bas.
diosney
Attention: cette fonction est obsolète depuis PHP 7.2.0. Il est fortement déconseillé de se fier à cette fonction.
shamaseen
15

Codez-le simplement comme ceci:

function example($anon) {
  $anon();
}

example(function(){
  // some codes here
});

ce serait formidable si vous pouviez inventer quelque chose comme ça (inspiré de Laravel Illuminate):

Object::method("param_1", function($param){
  $param->something();
});
Saint nuit
la source
exactement ce que je cherchais
Harvey
5

VERSION PHP> = 5.3.0

Exemple 1: basique

function test($test_param, $my_function) {
    return $my_function($test_param);
}

test("param", function($param) {
    echo $param;
}); //will echo "param"

Exemple 2: objet std

$obj = new stdClass();
$obj->test = function ($test_param, $my_function) {
    return $my_function($test_param);
};

$test = $obj->test;
$test("param", function($param) {
    echo $param;
});

Exemple 3: appel de classe non statique

class obj{
    public function test($test_param, $my_function) {
        return $my_function($test_param);
    }
}

$obj = new obj();
$obj->test("param", function($param) {
    echo $param;
});

Exemple 4: appel de classe statique

class obj {
    public static function test($test_param, $my_function) {
        return $my_function($test_param);
    }
}

obj::test("param", function($param) {
    echo $param;
});
Davit Gabrielyan
la source
5

Selon la réponse de @ zombat, il est préférable de valider d'abord les fonctions anonymes:

function exampleMethod($anonFunc) {
    //execute anonymous function
    if (is_callable($anonFunc)) {
        $anonFunc();
    }
}

Ou validez le type d'argument depuis PHP 5.4.0:

function exampleMethod(callable $anonFunc) {}
Nick Tsai
la source
comment gérez-vous quand la vérification (appelable $ anonFunc) a échoué? merci
xam
3

Testé pour PHP 5.3

Comme je le vois ici, Anonymous Function pourrait vous aider: http://php.net/manual/en/functions.anonymous.php

Ce dont vous aurez probablement besoin et ce n'est pas dit avant, c'est comment passer une fonction sans l'envelopper dans une fonction créée à la volée . Comme vous le verrez plus tard, vous devrez passer le nom de la fonction écrit dans une chaîne en tant que paramètre, vérifier sa "callabilité" puis l'appeler.

La fonction à faire vérifier:

if( is_callable( $string_function_name ) ){
    /*perform the call*/
}

Ensuite, pour l'appeler, utilisez ce morceau de code (si vous avez également besoin de paramètres, placez-les sur un tableau), vu à l' adresse : http://php.net/manual/en/function.call-user-func.php

call_user_func_array( "string_holding_the_name_of_your_function", $arrayOfParameters );

comme il suit (de manière similaire, sans paramètre):

    function funToBeCalled(){
        print("----------------------i'm here");
    }
    function wrapCaller($fun){
        if( is_callable($fun)){
            print("called");
            call_user_func($fun);
        }else{
            print($fun." not called");
        }
    }

    wrapCaller("funToBeCalled");
    wrapCaller("cannot call me");

Voici une classe expliquant comment faire quelque chose de similaire:

<?php
class HolderValuesOrFunctionsAsString{
    private $functions = array();
    private $vars = array();

    function __set($name,$data){
        if(is_callable($data))
            $this->functions[$name] = $data;
        else
            $this->vars[$name] = $data;
    }

    function __get($name){
        $t = $this->vars[$name];
        if(isset($t))
            return $t;
        else{
            $t = $this->$functions[$name];
            if( isset($t))
                return $t;
        }
    }

    function __call($method,$args=null){
        $fun = $this->functions[$method];
        if(isset($fun)){
            call_user_func_array($fun,$args);
        } else {
            // error out
            print("ERROR: Funciton not found: ". $method);
        }
    }
}
?>

et un exemple d'utilisation

<?php
    /*create a sample function*/
    function sayHello($some = "all"){
    ?>
         <br>hello to <?=$some?><br>
    <?php
    }

    $obj = new HolderValuesOrFunctionsAsString;

    /*do the assignement*/
    $obj->justPrintSomething = 'sayHello'; /*note that the given
        "sayHello" it's a string ! */

    /*now call it*/
    $obj->justPrintSomething(); /*will print: "hello to all" and
        a break-line, for html purpose*/

    /*if the string assigned is not denoting a defined method
         , it's treat as a simple value*/
    $obj->justPrintSomething = 'thisFunctionJustNotExistsLOL';

    echo $obj->justPrintSomething; /*what do you expect to print?
        just that string*/
    /*N.B.: "justPrintSomething" is treated as a variable now!
        as the __set 's override specify"*/

    /*after the assignement, the what is the function's destiny assigned before ? It still works, because it's held on a different array*/
     $obj->justPrintSomething("Jack Sparrow");


     /*You can use that "variable", ie "justPrintSomething", in both ways !! so you can call "justPrintSomething" passing itself as a parameter*/

     $obj->justPrintSomething( $obj->justPrintSomething );
         /*prints: "hello to thisFunctionJustNotExistsLOL" and a break-line*/

    /*in fact, "justPrintSomething" it's a name used to identify both
         a value (into the dictionary of values) or a function-name
         (into the dictionary of functions)*/
?>
Marco Ottina
la source
2

Exemple simple utilisant une classe:

class test {

    public function works($other_parameter, $function_as_parameter)
    {

        return $function_as_parameter($other_parameter) ;

    }

}

$obj = new test() ;

echo $obj->works('working well',function($other_parameter){


    return $other_parameter;


});
Softmixt
la source