在PHP中将函数作为参数传递

129

我一直在想是否可以在PHP中将一个函数作为参数传递。 我想要类似于JavaScript中编写以下代码时的效果:

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

我想要的是在 exampleMethod 中执行该函数,这在 PHP 中是否可行?


相关链接:https://dev59.com/gqfja4cB1Zd3GeqPpxHH#47634215 - alseether
9个回答

179

如果你正在使用 PHP 5.3.0 或更高版本,则可以实现。

请参见手册中的匿名函数

在你的情况下,你可以像这样定义exampleMethod

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

11
该死,我知道这是可能的。本来想回答,但想先找一些文件链接,而且不确定确切叫什么。啊,没关系,现在我知道了,以后需要做这个的时候就可以用上了。谢谢。 - Rob
3
5.3之前你可以使用create_function函数。 - Gordon
非常感谢。由于我必须为PHP4.3完成它,我想我将不得不使用另一种逻辑来实现我的目标。 - Cristian
1
@Casidiablo - 看看Jage的回答,你也许可以用create_function()来实现一些功能。虽然不完全相同,但你需要将函数作为代码字符串传递,然后在幕后使用eval()进行处理。这并不是最理想的方法,但你可能可以尝试使用它。 - zombat
2
你会怎么称呼它?你能给一个现有函数的名称吗?例如:exampleMethod(strpos); - sumid
exampleMethod函数的内容在哪里?匿名函数的内容在哪里? - Jovylle

64

补充其他答案,你可以传递一个函数名:

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

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

callFunc('someFunc');

这在 PHP4 中是可行的。


21

+1 for the alternative。听起来像是楼主需要它。 - zombat
谢谢!我必须坚持使用旧的PHP 5.2安装程序,而匿名函数在那里无法工作。 - Diosney
1
警告:自 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();
});

正是我所寻找的。 - harveyhans

10
根据@zombat的回答,最好首先验证匿名函数:
function exampleMethod($anonFunc) {
    //execute anonymous function
    if (is_callable($anonFunc)) {
        $anonFunc();
    }
}

从PHP 5.4.0开始,或者验证参数类型:

function exampleMethod(callable $anonFunc) {}

当 (callable $anonFunc) 检查失败时,您如何处理?谢谢。 - xam
@xam,你会得到一个PHP“TypeError”。你可以在try-catch块内处理它。https://www.php.net/manual/en/class.typeerror.php - Buttle Butkus

10

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

4

测试过适用于PHP 5.3

我在这里看到,匿名函数可以帮助您:http://php.net/manual/en/functions.anonymous.php

您可能需要的,但之前并未提到的是如何传递一个函数而不是将其包装在即时创建的函数内部。 后来您会发现,您需要将函数的名称以字符串形式作为参数传递,检查它的“可调用性”,然后调用它。

检查的函数:

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;


});

0
这是一个简单的过程示例,展示了如何使用单独的函数对多个数据项进行验证,并将它们作为函数数组参数传递给主验证函数。要验证的数据(即函数参数)作为另一个数组参数传递给主验证函数。这对于编写通用代码以验证表单数据非常有用。
<?php
function valX($value) {
    echo "<p>Validating $value == 5</p>";
    if ($value == 5) {
        return true;
    } else {
        return false;
    }
}

function valY($value) {
    echo "<p>Validating $value == 6</p>";
    if ($value == 6) {
        return true;
    } else {
        return false;
    }
}

function validate($values, $functions) {
    for ($i = 0; $i < count($values); $i++) {
        if ($functions[$i]($values[$i])) {
            echo "<p>$values[$i] passes validation</p>";
        } else {
            echo "<p>$values[$i] fails validation</p>";
        }
    }
}

$values = [5, 9];
$functions = ['valX', 'valY'];
validate($values, $functions);
?>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接