Pregunta Aceptar la función como parámetro en PHP


Me he estado preguntando si es posible o no pasar una función como parámetro en PHP; Quiero algo así como cuando estás programando en JS:

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

Lo que quiero es ejecutar esa función en algún lugar en exampleMethod. ¿Es eso posible en PHP?


73
2018-04-23 16:56


origen


Respuestas:


Es posible si usa PHP 5.3.0 o superior.

Ver Funciones anónimas en el manual.

En tu caso, definirías exampleMethod Me gusta esto:

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

113
2018-04-23 16:58



Solo para agregar a los demás, puede pasar un nombre de función:

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

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

callFunc('someFunc');

Esto funcionará en PHP4.


37
2018-04-23 17:46



También puedes usar create_function para crear una función como variable y pasarla. Sin embargo, me gusta la sensación de funciones anónimas mejor. Ve a zombi


14
2018-04-23 17:01



Simplemente codifícalo así:

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

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

sería genial si pudieras inventar algo como esto (inspirado en Laravel Illuminate):

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

11
2017-07-01 09:20



Según la respuesta de @Zombat, es mejor validar primero las Funciones anónimas:

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

O valide el tipo de argumento desde PHP 5.4.0:

function exampleMethod(callable $anonFunc) {}

3
2017-10-11 08:43



Ejemplo simple usando una clase:

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
2017-11-06 11:13



VERSIÓN PHP> = 5.3.0

Ejemplo 1: básico

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

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

Ejemplo 2: objeto estándar

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

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

Ejemplo 3: llamada de clase no estática

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

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

Ejemplo 4: llamada de clase estática

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

obj::test("param", function($param) {
    echo $param;
});

1
2018-05-21 13:31



Probado para PHP 5.3

Como veo aquí, la función anónima podría ayudarlo a: http://php.net/manual/en/functions.anonymous.php

Lo que probablemente necesitarás y no lo dijiste antes cómo pasar una función sin envolverla dentro de una función creada sobre la marcha. Como verá más adelante, deberá pasar el nombre de la función escrito en una cadena como parámetro, verificar su "capacidad de invocación" y luego llamarlo.

La función de hacer cheque:

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

Luego, para llamarlo, use este fragmento de código (si también necesita parámetros, colóquelos en una matriz), visto en: http://php.net/manual/en/function.call-user-func.php

call_user_func_array( "string_holding_the_name_of_your_function", $arrayOfParameters );

como sigue (de forma similar, sin parámetros):

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

Aquí hay una clase que explica cómo hacer algo similar:

<?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);
        }
    }
}
?>

y un ejemplo de uso

<?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)*/
?>

1
2017-11-30 00:38