Chấp nhận hàm làm tham số trong PHP


104

Tôi đã tự hỏi liệu có thể truyền một hàm làm tham số trong PHP hay không; Tôi muốn một cái gì đó giống như khi bạn lập trình trong JS:

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

Những gì tôi muốn là thực thi chức năng đó ở đâu đó trong exampleMethod. Điều đó có thể trong PHP không?


Câu trả lời:


150

Có thể thực hiện được nếu bạn đang sử dụng PHP 5.3.0 trở lên.

Xem Các chức năng ẩn danh trong sách hướng dẫn.

Trong trường hợp của bạn, bạn sẽ định nghĩa exampleMethodnhư thế này:

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

9
Chết tiệt, tôi biết điều đó là có thể. Định trả lời, nhưng muốn tìm một số tài liệu để liên kết đến trước, và không biết chính xác nó được gọi là gì. À, giờ thì tôi cũng sẽ biết khi nào tôi cần làm điều này. Cảm ơn.
Rob

3
Trước 5.3, bạn có thể sử dụngcreate_function
Gordon

Cảm ơn bạn rất nhiều. Vì tôi phải làm điều đó cho PHP4.3, tôi đoán tôi sẽ phải làm những gì tôi muốn bằng cách sử dụng một logic khác.
Cristian

1
@Casidiablo - Xem câu trả lời của Jage, bạn có thể làm được điều gì đó với create_function(). Nó không hoàn toàn giống như vậy, vì bạn phải chuyển hàm của mình dưới dạng một chuỗi mã, sau đó sẽ được thực hiện eval()phía sau. Không lý tưởng, nhưng bạn có thể sử dụng nó.
zombat

1
Bạn sẽ gọi nó như thế nào? Bạn có thể cung cấp cho một tên của chức năng hiện có? Vd:exampleMethod(strpos);
sumid

51

Chỉ cần thêm vào những cái khác, bạn có thể chuyển một tên hàm:

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

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

callFunc('someFunc');

Điều này sẽ hoạt động trong PHP4.


17

Bạn cũng có thể sử dụng create_ functions để tạo một hàm dưới dạng một biến và chuyển nó xung quanh. Mặc dù vậy, tôi thích cảm giác của các chức năng ẩn danh hơn. Đi zombat.


+1 cho lựa chọn thay thế. Có vẻ như OP có thể cần nó.
zombat

Cảm ơn! Tôi gắn bó với bản cài đặt PHP 5.2 cũ và các chức năng ẩn danh không hoạt động ở đó.
diosney

Cảnh báo: Chức năng này đã KHÔNG ĐƯỢC SỬ DỤNG kể từ phiên bản PHP 7.2.0. Việc dựa vào chức năng này rất không được khuyến khích.
shamaseen

15

Chỉ cần mã nó như thế này:

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

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

sẽ thật tuyệt nếu bạn có thể phát minh ra thứ như thế này (lấy cảm hứng từ Laravel Illuminate):

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

chính xác những gì tôi đang tìm kiếm
Harvey

5

PHIÊN BẢN PHP> = 5.3.0

Ví dụ 1: cơ bản

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

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

Ví dụ 2: đối tượng 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;
});

Ví dụ 3: cuộc gọi lớp không tĩnh

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

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

Ví dụ 4: lệnh gọi lớp tĩnh

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

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

5

Theo câu trả lời của @ zombat, tốt hơn nên xác thực các Hàm ẩn danh trước:

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

Hoặc xác thực loại đối số kể từ PHP 5.4.0:

function exampleMethod(callable $anonFunc) {}

3

Đã thử nghiệm cho PHP 5.3

Như tôi thấy ở đây, Chức năng ẩn danh có thể giúp bạn: http://php.net/manual/en/functions.anonymous.php

Những gì bạn có thể cần và nó chưa được nói trước đó là cách truyền một hàm mà không cần gói nó bên trong một hàm được tạo nhanh chóng . Như bạn sẽ thấy sau này, bạn sẽ cần chuyển tên của hàm được viết trong một chuỗi làm tham số, kiểm tra "khả năng gọi" của nó và sau đó gọi nó.

Chức năng kiểm tra:

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

Sau đó, để gọi nó, hãy sử dụng đoạn mã này (nếu bạn cũng cần tham số, hãy đặt chúng vào một mảng), xem tại: http://php.net/manual/en/ Chức năng.call-user-func.php

call_user_func_array( "string_holding_the_name_of_your_function", $arrayOfParameters );

như sau (theo cách tương tự, không tham số):

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

Đây là một lớp học giải thích cách làm điều gì đó tương tự:

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

và một ví dụ về cách sử dụng

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

Ví dụ đơn giản bằng cách sử dụng một lớp:

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;


});
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.