web-dev-qa-db-fra.com

Accepter la fonction en tant que paramètre dans PHP

Je me demandais s'il est possible ou non de passer une fonction en paramètre en PHP; Je veux quelque chose comme quand vous programmez dans 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?

88
Cristian

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 exampleMethod comme ceci:

function exampleMethod($anonFunc) {
    //execute anonymous function
    $anonFunc();
}
134
zombat

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.

44
webbiedave

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

15
Jage

Il suffit de le coder comme ceci:

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

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

ce serait génial si vous pouviez inventer quelque chose comme ceci (inspiré de Laravel Illuminate)):

Object::method("param_1", function($param){
  $param->something();
});
12
Saint Night

Selon la réponse de @ zombat, il est préférable de valider les fonctions anonymes en premier:

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) {}
5
Nick Tsai

VERSION PHP> = 5.3.0

Exemple 1: base

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;
});
3
Davit Gabrielyan

Testé pour PHP 5.3

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

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

La fonction à 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, mettez-le dans un tableau), visible à 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 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)*/
?>
2
Marco Ottina

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;


});
2
Softmixt