什么情况需要在php中使用call_user_func()

时间:2012-02-13 01:51:50

标签: php cakephp phpmyadmin php-5.3

我不理解函数,call_user_func()在某种意义上我知道它是如何工作的但是我不确定为什么它需要或在什么上下文中使用它在php中。就我而言,为什么不调用函数而不是用函数调用函数?日Thnx!

3 个答案:

答案 0 :(得分:2)

call_user_func 使PHP能够将方法和函数视为准一等公民。在像javascript这样的函数式语言中,不需要这些特殊工具本身,因为函数是一个碰巧可以调用的对象。

PHP越来越接近这种观念,特别是随着PHP5.3附带的关闭支持。看看我在@ deceze的答案下的评论。还有一些其他工具(即variable functionsreflection和现在closures)提供相同的基本功能。

call_user_func 最值得注意的是它如何允许您使用统一接口处理全局函数,静态类和对象。无论它们如何实现,它都可能是单个接口调用函数的最接近的东西。在内部,PHP核心开发人员团队正致力于some sort of a 'callable' or 'invokable' interface for the language的同质化,我相信我们会在PHP5.4或下一个主要版本中看到一个干净的产品。

答案 1 :(得分:1)

我有几种情况,这是非常必要的。例如,当我创建一个允许用户构造编程语言部分的项目时,系统会在运行它之前将“标记”定义包装在函数中,以保证安全性。但是,在这样做时,我不能简单地调用这些函数,因为我不知道何时需要调用它们,甚至不知道名称是什么。输入call_user_func()...

所以,我相信你现在很困惑。让我解释。我的系统所做的是获取一些XML,并使用PHP将其转换为PHP / HTML / JS。这允许快速创建GUI(这是目标)。以此XML为例:

<window id="login-win" title="Access Restricted" width="310" height="186" layout="accordion" layoutConfig="animate:true">
    <panel id="login-panel" title="User Login">
        <form id="login-form" title="Credentials">
            <textbox id="login-uname" label="Username"/>
            <password id="login-pass" label="Password"/>
            <submit text="Login"/>
        </form>
    </panel>
    <panel id="login-register" title="Register">
        Nothing, you can't register!
    </panel>
</window>

将读取每个XML标记,然后将其输入到相应的PHP函数中。该函数将决定如何为该1标记执行操作。为了解决这个问题,我将每个文件命名为它处理的标记。因此,例如,标签的文件是“submit.php”。该文件的内容将包含在生成的函数中,如:

function tag_submit($variables, $parent, $children){

    // deal with the data, then echo what is needed

}

此函数的名称将存储在一个数组中,与其关联的标记名称以及其余生成的函数一起存储。这使得函数生成一次,并且仅在需要时创建,节省内存,因为我会执行if(func_exists())调用以确定是否需要它。

然而,由于这都是动态的,并且用户可能想要添加新标签,例如,&lt;日期&gt;标签,我需要使用call_user_func()来使事情发挥作用。如果我不知道名字是什么,我就不能对函数调用进行硬编码。

希望一切都有意义。基本上,是的,它是一个很少使用的功能,但它仍然非常有用。

答案 2 :(得分:0)

命名函数,匿名函数,静态方法,实例方法和带有“__invoke”方法的对象统称为“callables”。如果我有一个可调用它可以通过后面放置括号来调用它“()”(我假设它不带参数)。当我们的callable存储在变量中时,这可以工作,例如:

$f();  // Call $f

但是,如果我将一个callable存储在一个object属性中呢?

$obj = new stdClass;
$obj->my_func = function() {};
$obj->my_func();  // Error: stdClass does not have a "my_func" method

问题是PHP的解析器变得混乱,因为代码含糊不清,可能意味着调用可调用属性或调用方法。 PHP选择始终将这种代码视为方法调用,因此我们不能以这种方式调用可调用属性。这就是我们需要'call_user_func'的原因:

call_user_func($obj->my_func); // Calls $obj->my_func

还有一些时候PHP不理解正常的括号语法;例如,PHP当前(5.5)不知道如何调用另一个可调用的返回值:

get_a_callable()();  // Parse error, unexpected "("
call_user_func(get_a_callable());  // Calls the return value of get_a_callable

目前还无法直接调用函数定义,这对于解决PHP缺少“let”语句很有用,例如:

function($x) { echo $x . $x; }('hello');  // Parse error, unexpected "("
call_user_func(function($x) { echo $x . $x; }, 'hello'); // Calls the function

有时候将函数调用/ reified /作为'call_user_func'函数是有用的。例如,使用像array_map这样的高阶函数时:

$funcs = [function() { return 'hello'; },
          function() { return 'world'; }];
array_map('call_user_func', $funcs);  // ['hello', 'world']

当我们不知道需要多少参数时,它也很有用,即。我们不能替换我们自己的“函数($ f,$ x,$ y,...){return $ f($ x,$ y,...);}”。

一个特别好的定义是部分应用程序,由于call_user_func和call_user_func_array,它只需要几行:

function partial() {
  $args1 = func_get_args();  // $f, $a, $b, $c, ...
  return function() use ($args1) {
    // Returns $f($a, $b, $c, ..., $d, $e, $f, ...)
    $args2 = func_get_args();  // $d, $e, $f, ...
    return call_user_func_array('call_user_func',
                                array_merge($args1, $args2));
  };
}