Terima fungsi sebagai parameter di PHP

104

Saya bertanya-tanya apakah mungkin atau tidak untuk melewatkan fungsi sebagai parameter di PHP; Saya ingin sesuatu seperti saat Anda memprogram di JS:

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

Yang saya inginkan adalah menjalankan fungsi itu di suatu tempat di exampleMethod. Apakah itu mungkin di PHP?

Cristian
sumber

Jawaban:

150

Itu mungkin jika Anda menggunakan PHP 5.3.0 atau lebih tinggi.

Lihat Fungsi Anonim di manual.

Dalam kasus Anda, Anda akan mendefinisikan exampleMethodseperti ini:

function exampleMethod($anonFunc) {
    //execute anonymous function
    $anonFunc();
}
zombat
sumber
9
Sial, aku tahu itu mungkin. Akan menjawab, tetapi ingin menemukan beberapa dokumentasi untuk ditautkan terlebih dahulu, dan tidak tahu persis apa namanya. Ah, baiklah, sekarang saya akan tahu kapan saya perlu melakukan ini juga. Terima kasih.
Rob
3
Sebelum 5.3 Anda dapat menggunakancreate_function
Gordon
Terima kasih banyak. Karena saya harus melakukannya untuk PHP4.3, saya rasa saya harus melakukan apa yang saya inginkan menggunakan logika lain.
Cristian
1
@Casidiablo - Lihat jawaban Jage, Anda mungkin bisa melakukan sesuatu dengan create_function(). Ini tidak persis sama, karena Anda harus meneruskan fungsi Anda sebagai string kode, yang kemudian eval()berada di belakang layar. Tidak ideal, tetapi Anda mungkin bisa menggunakannya.
zombat
1
Bagaimana Anda menyebutnya? Bisakah Anda memberi nama fungsi yang ada? Misalnya:exampleMethod(strpos);
sumid
51

Hanya untuk menambah yang lain, Anda dapat memberikan nama fungsi:

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

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

callFunc('someFunc');

Ini akan bekerja di PHP4.

webbiedave
sumber
17

Anda juga dapat menggunakan create_function untuk membuat fungsi sebagai variabel dan menyebarkannya. Padahal, saya suka perasaan fungsi anonim lebih baik. Pergi zombat.

Jage
sumber
1 untuk alternatifnya. Sepertinya OP mungkin membutuhkannya.
zombat
Terima kasih! Saya harus tetap menggunakan instalasi PHP 5.2 lama dan fungsi anonymoys tidak berfungsi di sana.
diosney
Peringatan: Fungsi ini TIDAK DIGUNAKAN LAGI pada PHP 7.2.0. Mengandalkan fungsi ini sangat tidak disarankan.
shamaseen
15

Cukup kodekan seperti ini:

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

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

akan sangat bagus jika Anda dapat menemukan sesuatu seperti ini (terinspirasi oleh Laravel Illuminate):

Object::method("param_1", function($param){
  $param->something();
});
Saint Night
sumber
persis seperti yang saya cari
Harvey
5

VERSI PHP> = 5.3.0

Contoh 1: dasar

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

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

Contoh 2: objek 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;
});

Contoh 3: panggilan kelas non-statis

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

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

Contoh 4: panggilan kelas statis

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

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

Menurut jawaban @ zombat, sebaiknya validasi Fungsi Anonim dulu:

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

Atau validasi tipe argumen sejak PHP 5.4.0:

function exampleMethod(callable $anonFunc) {}
Nick Tsai
sumber
bagaimana Anda menangani ketika pemeriksaan (callable $ anonFunc) gagal? terima kasih
xam
3

Diuji untuk PHP 5.3

Seperti yang saya lihat di sini, Fungsi Anonim dapat membantu Anda: http://php.net/manual/en/functions.anonymous.php

Apa yang mungkin Anda perlukan dan tidak disebutkan sebelumnya adalah cara meneruskan fungsi tanpa membungkusnya di dalam fungsi yang dibuat dengan cepat . Seperti yang akan Anda lihat nanti, Anda harus meneruskan nama fungsi yang ditulis dalam string sebagai parameter, periksa "callability" -nya lalu panggil.

Fungsi untuk melakukan pengecekan:

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

Kemudian, untuk menyebutnya, gunakan bagian kode ini (jika Anda juga membutuhkan parameter, letakkan di array), lihat di: http://php.net/manual/en/function.call-user-func.php

call_user_func_array( "string_holding_the_name_of_your_function", $arrayOfParameters );

sebagai berikut (dengan cara yang serupa, tanpa parameter,):

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

Berikut adalah kelas yang menjelaskan cara melakukan sesuatu yang serupa:

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

dan contoh penggunaan

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

Contoh sederhana menggunakan kelas:

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
sumber