PHP函数处理 函数(1): call_user_func(_array)、func_get_arg(s)、func_num_args

函数简介

call_user_func_array

mixed call_user_func_array ( callable $callback , array $param_arr )
把第一个参数作为回调函数(callback)调用,把参数数组(param_arr)作为回调函数的的参数传入。param_arr 要被传入回调函数的数组,这个数组得是索引数组。参数可以引用传递。

call_user_func

mixed call_user_func ( callable $callback [, mixed $parameter [, mixed $… ]] )
第一个参数 callback 是被调用的回调函数,其余参数是回调函数的参数。
parameter 0个或以上的参数,被传入回调函数。传入call_user_func()的参数不能为引用传递。

func_get_args

array func_get_args ( void ) 获取函数参数列表的数组。
返回一个数组,其中每个元素都是目前用户自定义函数的参数列表的相应元素的副本。

func_num_args

int func_num_args ( void )
Gets the number of arguments passed to the function.

func_get_arg

mixed func_get_arg ( int $arg_num )
从用户自定义函数的参数列表中获取某个指定的参数。
arg_num 参数的偏移量。函数的参数是从0开始计数的。当 arg_num 比实际传入的参数的数目大或小于0的时候发出一个警告,返回 FALSE 。

应用

call_user_func_array

场景一:函数名是未知、函数的参数类型及个数也是未知的
场景二:用于函数回调,回调函数可能是一个普通函数(动态调用普通函数,类似可变函数),可能是类方法,也可能是静态方法。如果使用call_user_func_array,你就不用去判断方法的类型

可以调用静态方法

class mrClass {

  function test() {
    if (is_object($this)) {
      // do something for instance method 实例调用
      echo 'this is an instance call <br />' . "\n";
    } else {
      // do something different for procedural method
      echo 'this is a procedure call <br />' . "\n";
    }
  }

  static function testStatic() {
    if (is_object($this)) {
      // do something for instance method 实例调用
      echo 'this is an instance call <br />' . "\n";
    } else {
      // do something different for procedural method
      echo 'this is a procedure call <br />' . "\n";
    }
  }
}

$inst = new mrClass();
$inst->test();

//Strict standards: Non-static method mrClass::test() should not be called statically
mrClass::test();//静态调用,没有生成$this,输出$this为null,并报错。is_object(null)返回false

//Strict standards: Non-static method mrClass::test() should not be called statically
mrClass::testStatic();//静态调用,没有生成$this,输出$this为null,并报错

echo '<hr>';

//Notice: Undefined variable: this, $this报的错,而不是调用报的错
call_user_func_array(array('mrClass','testStatic'),[]);

可以引用

function increment(&$var)
{
  $var++;
}

$a = 0;
//call_user_func('increment', &$a);//Fatal error: Call-time pass-by-reference has been removed in ...
call_user_func('increment', $a);//Warning: Parameter 1 to increment() expected to be a reference, value given in ...

echo $a."\n";

call_user_func_array('increment', array(&$a)); // You can use this instead before PHP 5.3
echo $a."\n";

//以上例程会输出:
//0
//1

func_num_args、func_get_arg

function foo()
{
    $numargs = func_num_args();
    echo "Number of arguments: $numargs<br />\n";
    if ($numargs >= 2) {
        echo "Second argument is: " . func_get_arg(1) . "<br />\n";
        //var_dump(func_get_arg(-1)); //Warning: func_get_arg(): The argument number should be >= 0 in 。。。
        //var_dump(func_get_arg(6)); //Warning: func_get_arg(): Argument 6 not passed to function in 。。。
    }
    $arg_list = func_get_args();
    for ($i = 0; $i < $numargs; $i++) {
        echo "Argument $i is: " . $arg_list[$i] . "<br />\n";
    }
}

foo(1, 2, 3);

/*
以上例程会输出:
    Number of arguments: 3<br />
    Second argument is: 2<br />
    Argument 0 is: 1<br />
    Argument 1 is: 2<br />
    Argument 2 is: 3<br />
*/

call_user_func与直接调用速度区别

在php中,使用“变量函数”(variiable function)会比call_user_func()慢,而call_user_func_array()比call_user_func()还要更慢。

相关的benchmark如下:


# Benchmark (2 million iterations)

# Operation                    Seconds
# Literal function          1.218
# Variable function         1.305
# call_user_func()          2.734
# call_user_func_array()    3.386

可以看到,变量函数和普通函数调用(literal function)速度差别不大,和call_user_func相差有一倍以上,而call_user_func_array则要更慢。所以你给的代码才会尽量避免使用call_user_func_array而更倾向于使用变量函数。因为只有很少的函数会有5个以上的参数,所以上面代码里才把1到5个函数的调用用变量函数来写,而只留下小部分的函数用call_user_func_array调用,从而最大的加快程序执行速度。

其实,这些函数的效率差异不会有想象的那么大,上面的benchmark是迭代200万次的结果,如果你的程序只会调用’call_user_func_array’几千次或以下,这些差异将会非常小(大概是0.002秒左右)。

参考

php.net
php call_user_func_array函数有什么不好的地方吗?
php问题 call_user_func_array 这个函数什么时候用?最近再看tp框架 很多地方用到了这个函数
使用call_user_func_array()来回调执行函数与直接使用函数的区别是什么?
Benchmarking magic–PHP

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值