Funktion als Parameter in PHP akzeptieren


104

Ich habe mich gefragt, ob es möglich ist, eine Funktion als Parameter in PHP zu übergeben. Ich möchte so etwas wie beim Programmieren in JS:

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

Ich möchte diese Funktion irgendwo in exampleMethod ausführen. Ist das in PHP möglich?


Antworten:


150

Es ist möglich, wenn Sie PHP 5.3.0 oder höher verwenden.

Siehe Anonyme Funktionen im Handbuch.

In Ihrem Fall würden Sie Folgendes definieren exampleMethod:

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

9
Verdammt, ich wusste, dass es möglich war. Ich wollte antworten, wollte aber zuerst eine Dokumentation finden, auf die ich verlinken konnte, und wusste nicht, wie sie genau heißt. Na ja, jetzt weiß ich, wann ich das auch tun muss. Vielen Dank.
Rob

3
Vor 5.3 können Sie verwendencreate_function
Gordon

Ich danke dir sehr. Da ich es für PHP4.3 tun muss, muss ich wohl mit einer anderen Logik tun, was ich will.
Cristian

1
@Casidiablo - Siehe Jages Antwort, vielleicht kannst du etwas damit anfangen create_function(). Es ist nicht ganz dasselbe, da Sie Ihre Funktion als Code-Zeichenfolge übergeben müssen, die dann eval()hinter die Kulissen gelangt. Nicht ideal, aber Sie können es möglicherweise verwenden.
Zombat

1
Wie würden Sie es nennen? Könnten Sie einen Namen für die vorhandene Funktion angeben? ZB:exampleMethod(strpos);
sumid

51

Um den anderen etwas hinzuzufügen, können Sie einen Funktionsnamen übergeben:

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

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

callFunc('someFunc');

Dies wird in PHP4 funktionieren.


17

Sie können auch create_function verwenden , um eine Funktion als Variable zu erstellen und weiterzugeben. Das Gefühl anonymer Funktionen gefällt mir allerdings besser. Geh zombat.


+1 für die Alternative. Es klingt so, als ob das OP es brauchen könnte.
Zombat

Vielen Dank! Ich muss mich an eine alte PHP 5.2-Installation halten und anonymoys-Funktionen funktionieren dort nicht.
Diosney

Warnung: Diese Funktion wurde ab PHP 7.2.0 VERRINGERT. Es wird dringend davon abgeraten, sich auf diese Funktion zu verlassen.
Shamaseen

15

Codieren Sie es einfach so:

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

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

Es wäre großartig, wenn Sie so etwas erfinden könnten (inspiriert von Laravel Illuminate):

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

genau das, wonach ich gesucht habe
Harvey

5

PHP-VERSION> = 5.3.0

Beispiel 1: Grundlegend

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

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

Beispiel 2: Standardobjekt

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

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

Beispiel 3: Nicht statischer Klassenaufruf

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

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

Beispiel 4: statischer Klassenaufruf

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

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

5

Laut der Antwort von @ zombat ist es besser, zuerst die anonymen Funktionen zu validieren:

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

Oder überprüfen Sie den Argumenttyp seit PHP 5.4.0:

function exampleMethod(callable $anonFunc) {}

3

Getestet für PHP 5.3

Wie ich hier sehe, könnte Anonymous Function Ihnen helfen: http://php.net/manual/en/functions.anonymous.php

Was Sie wahrscheinlich brauchen und es wird nicht gesagt, bevor Sie eine Funktion übergeben, ohne sie in eine im laufenden Betrieb erstellte Funktion einzuschließen . Wie Sie später sehen werden, müssen Sie den in eine Zeichenfolge geschriebenen Funktionsnamen als Parameter übergeben, die "Aufrufbarkeit" überprüfen und ihn dann aufrufen.

Die zu überprüfende Funktion:

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

Verwenden Sie dann, um es aufzurufen, diesen Code (wenn Sie auch Parameter benötigen, fügen Sie diese in ein Array ein), siehe: http://php.net/manual/en/function.call-user-func.php

call_user_func_array( "string_holding_the_name_of_your_function", $arrayOfParameters );

wie folgt (auf ähnliche, parameterlose Weise):

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

Hier ist eine Klasse, die erklärt, wie man etwas Ähnliches macht:

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

und ein Anwendungsbeispiel

<?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

Einfaches Beispiel mit einer Klasse:

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;


});
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.