PHP call_user_func的一些用法和注意点
版本:PHP 5.6.28
在call_user_func的调用中:
1.参数的传递过程,并不是引用传值。
1 error_reporting(E_ERROR); // 此处不是E_ALL
2 $cur_value = 1;
3
4 function increment(&$var)
5 {
6 $var++;
7 }
8 echo 'Before value is :' .$cur_value. "\n";
9 call_user_func('increment',$cur_value);
10 echo 'After call call_user_func : ' .$cur_value. "\n";
在E_ALL的报告级别下,可以看到控制台的有此输出:

如果要引用传值,可以使用call_user_func_array ;
1 call_user_func_array('increment',array(&$cur_value));
2. PHP版本不大于5.3.0时,对面向对象里面的关键字的解析有所增强。在此之前,使用双引号来来连接一个类和里面的一个方法,把之作为参数来作为回调函数的会,将会发出一个 E_STRICT的警告,因为这个传入的参数被视为静态方法。
3. 变量函数比call_user_func效率高点,在一下的情况可以考虑使用call_user_func:
<?php
function say($content)
{
echo $content ."\n";
}
$content = 'Hello the world!';
$func = 'say'; echo 'Say the classic word one thousands times!' ."\n"; echo 'Called by the Variable Function' ."\n";
$start = microtime(true);
for($i = 0;$i < 10000;$i++)
{
$func($content);
}
$end = microtime(true);
$time1 = $end - $start; echo 'Called by the call_user_func function ' ."\n";
$start = microtime(true);
for($i = 0;$i < 10000;$i++)
{
call_user_func($func,$content);
}
$end = microtime(true);
$time2 = $end - $start; echo 'Variable Function Cost ' .$time1. ' microseconds!' ."\n";
echo 'Function of call_user_func Cost ' .$time2. ' microsecond!' ."\n";
win10终端输出:

phpstorm的终端:

注意:此截图是在win10控制台直接输出的单词结果,多次运行之后,时间并没有相差很大,但是变量函数平均的情况下还是稍快。
我直接在IDE phpstorm的终端多次测试运行之后,发现相比在控制台的输出,运行时间两个减了将近一半,可能有优化输出。
4.调用类中的方法,如果是静态的方法,可以通过命名空间加方法命直接调用;如果是非静态的方法,可以先实例化一个对象,通过对象和方法命组成的数组作为参数被调用。
1 <?php
2 namespace Test;
3
4 class Test
5 {
6 static public function greet()
7 {
8 echo 'Hello the world!' ."\n";
9 }
10
11 public function say()
12 {
13 echo 'Good morning, sir!' ."\n";
14 }
15 }
16
17 call_user_func(__NAMESPACE__ .'\Test::greet');
18 call_user_func(array(__NAMESPACE__ .'\Test','greet'));
19
20 $test = new Test();
21 call_user_func(array($test,'say'));
5. 在引用别人的代码时,可能会有函数名称冲突的可能。如果是递归函数,可能就要修改内部的函数代码。使用call_user_func可以避免修改内部的代码。
function qwertyuiop($i=1) {
return($i==1?1:$i*call_user_func(__FUNCTION__,$i-1));
}
不过,个人觉得可以用变量函数代替使用call_user_func函数,可以吗?
PHP call_user_func的一些用法和注意点的更多相关文章
- php call_user_func和call_user_func_array
首先要看这个页面关于callable类型:http://www.php.net/manual/zh/language.types.callable.php 自 PHP 5.4 起可用 callable ...
- ASP.NET Core 中文文档 第二章 指南(4.10)检查自动生成的Detail方法和Delete方法
原文 Examining the Details and Delete methods 作者 Rick Anderson 翻译 谢炀(Kiler) 校对 许登洋(Seay).姚阿勇(Mr.Yao) 打 ...
- call_user_func()的参数不能为引用传递 自定义替代方法
php手册 中关于 请注意,传入call_user_func()的参数不能为引用传递. 关于这个情况的解释,可自己搜索.我们可以自己定义一个函数解决这样的问题,实例如下: <?php ini_s ...
- Spark Rdd coalesce()方法和repartition()方法
在Spark的Rdd中,Rdd是分区的. 有时候需要重新设置Rdd的分区数量,比如Rdd的分区中,Rdd分区比较多,但是每个Rdd的数据量比较小,需要设置一个比较合理的分区.或者需要把Rdd的分区数量 ...
- 最小生成树---Prim算法和Kruskal算法
Prim算法 1.概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (gra ...
- set和enum类型的用法和区别
mysql中的set和enum类型的用法和区别 mysql中的enum和set其实都是string类型的而且只能在指定的集合里取值, 不同的是set可以取多个值,enum只能取一个值. 1 2 3 ...
- 【体系结构】动态调度算法:记分牌算法和tomasulo算法
记分牌和tomasulo算法 动态调度: 通过硬件在程序执行时重新安排代码的执行序列来减少竞争引起的流水线停顿时间 动态调度流水线具备以下功能: (1)允许按序取多条指令和发射多条指令----取指(I ...
- 《ES6基础教程》之 Call 方法和 Apply 方法
<script type="text/javascript"> // Call方法: // 语法:call(thisObj[,arg1,arg2,...,argN]) ...
- Javascript中数组方法和方法的扩展
最近一直在努力的恶补javascript中的各种知识,比如说闭包,作用域,继承,构造函数,变量,内置对象等概念.同时,也在学习着ES6的新知识.最近想给大家分享的就是数组实例方法的练习以及如何去扩展一 ...
随机推荐
- Java第二次作业第一题
编写图形界面程序,在窗体中设置菜单栏,在菜单栏上添加"file"菜单,在文件菜单中添加"new"和"quit"两个菜单项,其中"q ...
- DirectX12 3D 游戏开发与实战第四章内容(下)
Direct3D的初始化(下) 学习目标 了解Direct3D在3D编程中相对于硬件所扮演的角色 理解组件对象模型COM在Direct3D中的作用 掌握基础的图像学概念,例如2D图像的存储方式,页面翻 ...
- [LeetCode] 由 “分形" 所想
分形思想和递归思想有区别么? 一.简单例子 函数调用自己,简化了理解逻辑,但其他到处都是问题. #%% def listsum(numList): if len(numList) == 1: retu ...
- php根据经纬度排序,根据经纬度筛选距离段
SQL 语句:select location.* from (select *,round(6378.138*2*asin(sqrt(pow(sin( (36.668530*pi()/180-px_l ...
- C# 代码往oracle数据库添加datetime格式列
C# 代码往oracle数据库添加datetime格式列时,不需要在insert语句中为datetime类型使用to_date函数
- 视频转成在github的readme中展示项目的gif动图
本文中涉及的FastStone Capture和FFmpeg两个软件的百度网盘链接: 链接:https://pan.baidu.com/s/1D5LO9Qmjl-vwJZfnbAloyQ 提取码:56 ...
- 在vue项目中使用less
1.安装 less 和 less-loader. 命令: npm install less less-loader --save-dev 2.打开 build/webpack.ba ...
- Atm 测试
Account.java package ATM;//信1705-1 20173628 赵路仓 public class Account { private int balance;//余额 priv ...
- SpringSecurity原理剖析与权限系统设计
Spring Secutity和Apache Shiro是Java领域的两大主流开源安全框架,也是权限系统设计的主要技术选型.本文主要介绍Spring Secutity的实现原理,并基于Spring ...
- Docker service endpoint with name xxx already exist问题
这是因为利用docker compose启的容器再用docker rm命令删除后,网络仍然被占用,需要手动清理 解决办法: 先用docker rm -f xxx删除容器 再输入docker netwo ...