ยอมรับฟังก์ชันเป็นพารามิเตอร์ใน PHP


105

ฉันสงสัยว่าเป็นไปได้หรือไม่ที่จะส่งฟังก์ชันเป็นพารามิเตอร์ใน PHP ฉันต้องการบางอย่างเช่นเมื่อคุณเขียนโปรแกรมใน JS:

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

สิ่งที่ฉันต้องการคือเรียกใช้ฟังก์ชันนั้นที่ใดที่หนึ่งใน exampleMethod เป็นไปได้ใน PHP หรือไม่?


ที่เกี่ยวข้อง: stackoverflow.com/questions/47502068/…
พร้อมกัน

คำตอบ:


151

เป็นไปได้ถ้าคุณใช้ PHP 5.3.0 ขึ้นไป

ดูAnonymous Functionsในคู่มือ

ในกรณีของคุณคุณจะกำหนดexampleMethodดังนี้:

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

9
ให้ตายเถอะฉันรู้ว่ามันเป็นไปได้ กำลังจะตอบ แต่อยากหาเอกสารมาลิงค์ก่อนเลยไม่รู้ว่าเรียกว่าอะไรกันแน่ อืมตอนนี้ฉันจะรู้แล้วว่าเมื่อไหร่ที่ต้องทำเช่นกัน ขอบคุณ.
Rob

3
ก่อน 5.3 คุณสามารถใช้ได้create_function
Gordon

ขอบคุณมาก. เนื่องจากฉันต้องทำเพื่อ PHP4.3 ฉันเดาว่าฉันจะต้องทำสิ่งที่ฉันต้องการโดยใช้ตรรกะอื่น
Cristian

1
@Casidiablo - ดูคำตอบของ Jage คุณอาจสามารถทำอะไรบางอย่างcreate_function()ได้ มันไม่เหมือนกันมากนักเนื่องจากคุณต้องส่งฟังก์ชันของคุณเป็นสตริงรหัสซึ่งจะได้รับeval()'d เบื้องหลัง ไม่เหมาะ แต่คุณอาจจะใช้งานได้
zombat

1
คุณจะเรียกมันว่าอย่างไร? คุณช่วยตั้งชื่อฟังก์ชันที่มีอยู่ได้ไหม เช่น:exampleMethod(strpos);
sumid

52

เพียงแค่เพิ่มไปยังรายการอื่น ๆ คุณสามารถส่งชื่อฟังก์ชัน:

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

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

callFunc('someFunc');

สิ่งนี้จะทำงานใน PHP4


17

คุณยังสามารถใช้create_functionเพื่อสร้างฟังก์ชันเป็นตัวแปรและส่งผ่านไปรอบ ๆ แม้ว่าฉันชอบความรู้สึกของฟังก์ชันนิรนามมากกว่า ไป zombat


+1 สำหรับทางเลือก ดูเหมือนว่า OP อาจจำเป็นต้องใช้
zombat

ขอบคุณ! ฉันติดการติดตั้ง PHP 5.2 แบบเก่าและฟังก์ชัน anonymoys ไม่ทำงานที่นั่น
diosney

คำเตือน: ฟังก์ชันนี้ถูกเลิกใช้งานเมื่อ PHP 7.2.0 การใช้ฟังก์ชันนี้เป็นสิ่งที่ไม่ควรทำอย่างยิ่ง
shamaseen

15

เพียงแค่เขียนโค้ดดังนี้:

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

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

มันจะดีมากถ้าคุณสามารถประดิษฐ์อะไรแบบนี้ (ได้รับแรงบันดาลใจจาก Laravel Illuminate):

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

สิ่งที่ฉันกำลังมองหา
Harvey

5

เวอร์ชัน PHP> = 5.3.0

ตัวอย่างที่ 1: พื้นฐาน

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

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

ตัวอย่างที่ 2: วัตถุ 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;
});

ตัวอย่างที่ 3: การเรียกคลาสแบบไม่คงที่

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

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

ตัวอย่างที่ 4: การเรียกคลาสแบบคงที่

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

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

5

ตามคำตอบของ @ zombat ควรตรวจสอบความถูกต้องของฟังก์ชันนิรนามก่อน:

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

หรือตรวจสอบประเภทอาร์กิวเมนต์ตั้งแต่ PHP 5.4.0:

function exampleMethod(callable $anonFunc) {}

คุณจะจัดการอย่างไรเมื่อการตรวจสอบ (เรียก $ anonFunc) ล้มเหลว ขอบคุณ
xam

3

ทดสอบ PHP 5.3

ดังที่ฉันเห็นที่นี่ฟังก์ชัน Anonymous สามารถช่วยคุณได้: http://php.net/manual/en/functions.anonymous.php

สิ่งที่คุณอาจต้องการและไม่ได้บอกไว้ก่อนว่าจะส่งผ่านฟังก์ชันโดยไม่รวมไว้ในฟังก์ชันที่สร้างขึ้นได้ทันที ดังที่คุณจะเห็นในภายหลังคุณจะต้องส่งชื่อของฟังก์ชันที่เขียนเป็นสตริงเป็นพารามิเตอร์ตรวจสอบ "callability" แล้วจึงเรียกมัน

ฟังก์ชั่นที่ต้องตรวจสอบ:

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

จากนั้นหากต้องการเรียกใช้รหัสนี้ (หากคุณต้องการพารามิเตอร์ให้วางไว้บนอาร์เรย์) ดูได้ที่: http://php.net/manual/en/function.call-user-func.php

call_user_func_array( "string_holding_the_name_of_your_function", $arrayOfParameters );

ดังต่อไปนี้ (ในลักษณะที่คล้ายกันไม่มีพารามิเตอร์):

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

นี่คือชั้นเรียนที่อธิบายวิธีการทำสิ่งที่คล้ายกัน:

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

และตัวอย่างการใช้งาน

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

ตัวอย่างง่ายๆโดยใช้คลาส:

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;


});
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.