call_user_func_array

(PHP 4 >= 4.0.4, PHP 5, PHP 7, PHP 8)

call_user_func_array使用参数数组调用回调函数

描述

call_user_func_array(callable $callback, array $args): mixed

使用第一个参数给出的 callback,并使用 args 中的参数进行调用。

参数

callback

要调用的 callable

args

要传递给回调函数的参数,以数组形式。

如果 args 的键都是数字,则忽略键,每个元素将按顺序作为位置参数传递给 callback

如果 args 的任何键是字符串,则这些元素将作为命名参数传递给 callback,键名作为参数名。

args 中,数字键出现在字符串键之后,或者字符串键与 callback 的任何参数名不匹配,都是致命错误。

返回值

返回回调函数的返回值,如果发生错误,则返回 false

变更日志

版本 描述
8.0.0 args 的键现在将被解释为参数名,而不是被静默忽略。

示例

示例 #1 call_user_func_array() 示例

<?php
function foobar($arg, $arg2) {
echo
__FUNCTION__, " got $arg and $arg2\n";
}
class
foo {
function
bar($arg, $arg2) {
echo
__METHOD__, " got $arg and $arg2\n";
}
}


// 使用 2 个参数调用 foobar() 函数
call_user_func_array("foobar", array("one", "two"));

// 使用 2 个参数调用 $foo->bar() 方法
$foo = new foo;
call_user_func_array(array($foo, "bar"), array("three", "four"));
?>

上面的示例将输出类似以下内容

foobar got one and two
foo::bar got three and four

示例 #2 call_user_func_array() 使用命名空间名称

<?php

namespace Foobar;

class
Foo {
static public function
test($name) {
print
"Hello {$name}!\n";
}
}

call_user_func_array(__NAMESPACE__ .'\Foo::test', array('Hannes'));

call_user_func_array(array(__NAMESPACE__ .'\Foo', 'test'), array('Philip'));

?>

上面的示例将输出类似以下内容

Hello Hannes!
Hello Philip!

示例 #3 使用 lambda 函数

<?php

$func
= function($arg1, $arg2) {
return
$arg1 * $arg2;
};

var_dump(call_user_func_array($func, array(2, 4)));

?>

上面的示例将输出

int(8)

示例 #4 按引用传递值

<?php

function mega(&$a){
$a = 55;
echo
"function mega \$a=$a\n";
}
$bar = 77;
call_user_func_array('mega',array(&$bar));
echo
"global \$bar=$bar\n";

?>

上面的示例将输出

function mega $a=55
global $bar=55

示例 #5 call_user_func_array() 使用命名参数

<?php
function foobar($first, $second) {
echo
__FUNCTION__, " got $first and $second\n";
}

// 使用非位置顺序的命名参数调用 foobar() 函数
call_user_func_array("foobar", array("second" => "two", "first" => "one"));

// 使用一个命名参数调用 foobar() 函数
call_user_func_array("foobar", array("foo", "second" => "bar"));

// 致命错误:无法在命名参数之后使用位置参数
call_user_func_array("foobar", array("first" => "one", "bar"));

?>

上面的示例将输出类似以下内容

foobar got one and two
foobar got foo and bar

Fatal error: Uncaught Error: Cannot use positional argument after named argument

备注

注意:

如果在先前的回调函数中抛出未捕获的异常,则使用 call_user_func()call_user_func_array() 等函数注册的回调函数将不会被调用。

参见

添加笔记

用户贡献笔记 4 个笔记

admin at torntech dot com
9 年前
从 PHP 5.6 开始,您可以使用参数解包作为 call_user_func_array 的替代方案,并且通常快 3 到 4 倍。

<?php
function foo ($a, $b) {
return
$a + $b;
}

$func = 'foo';
$values = array(1, 2);
call_user_func_array($func, $values);
// 返回 3

$func(...$values);
// 返回 3
?>

来自 https://gist.github.com/nikic/6390366 的基准测试
cufa 使用 0 个参数花费了 0.43453288078308 秒
switch 使用 0 个参数花费了 0.24134302139282 秒
unpack 使用 0 个参数花费了 0.12418699264526 秒
cufa 使用 5 个参数花费了 0.73408579826355 秒
switch 使用 5 个参数花费了 0.49595499038696 秒
unpack 使用 5 个参数花费了 0.18640494346619 秒
cufa 使用 100 个参数花费了 5.0327250957489 秒
switch 使用 100 个参数花费了 5.291127204895 秒
unpack 使用 100 个参数花费了 1.2362589836121 秒
sebastian dot rapetti at tim dot it
3 年前
使用 PHP 8,如果传递给 $args 参数的数组带有键,则 call_user_func_array 将使用命名参数调用回调函数;如果使用的数组只有值,则参数将按位置传递。

<?php

function test(string $param1, string $param2): void
{
echo
$param1.' '.$param2;
}

$args = ['hello', 'world'];
// hello world
call_user_func_array('test', $args);

$args = ['param2' => 'world', 'param1' => 'hello'];
// hello world
call_user_func_array('test', $args);

$args = ['unknown_param' => 'hello', 'param2' => 'world'];
// 致命错误: 未捕获的错误: 未知的命名参数 $unknown_param
call_user_func_array('test', $args);
?>
alangiderick at gmail dot com
11 个月前
阅读此页面上的笔记非常有趣,特别是 admin at torntech dot com 提到的关于参数解包比直接调用 call_user_func_array() 快得多的笔记。

这在 PHP 5 中是正确的,但从 PHP 7.0+ 开始,这两种操作机制之间的运行时没有显著差异。两种操作花费的时间几乎相同,如果不是完全相同的话,这告诉我 PHP 运行时环境已经发生了很大变化(对于 PHP 7 的重写)。

我使用 admin at torntech dot com 中的示例来验证这个假设。
james at gogo dot co dot nz
19 年前
请注意,call_user_func_array 始终按值返回,如下所示...

<?php
function &foo($a)
{
return
$a;
}

$b = 2;
$c =& call_user_func_array('foo', array(&$b));
$c++;
echo
$b . ' ' . $c;
?>

输出 "2 3",而不是预期的 "3 3"。

以下是一个您可以用来代替 call_user_func_array 的函数,它返回对函数调用结果的引用。

<?php
function &ref_call_user_func_array($callable, $args)
{
if(
is_scalar($callable))
{
// $callable 是函数名称
$call = $callable;
}
else
{
if(
is_object($callable[0]))
{
// $callable 是一个对象和一个方法名
$call = "\$callable[0]->{$callable[1]}";
}
else
{
// $callable 是一个类名和一个静态方法
$call = "{$callable[0]}::{$callable[1]}";
}
}

// 注意因为 $args 中的键可能是字符串
// 我们以一种稍微迂回的方式做到这一点。
$argumentString = array();
$argumentKeys = array_keys($args);
foreach(
$argumentKeys as $argK)
{
$argumentString[] = "\$args[$argumentKeys[$argK]]";
}
$argumentString = implode($argumentString, ', ');
// 注意 eval 也不返回引用,所以我们
// 用这种方式解决...
eval("\$result =& {$call}({$argumentString});");
return
$result;
}
?>
To Top