解析数组非数字键名引号的必要性


Posted in PHP onAugust 09, 2013

我看到过很多人操作数组的时候, 对于数组中的非数字键名不使用引号

  $array[key] = $value;

我可以理解有些人可能会觉得这样的代码很”整洁”, 并且也能正常执行.
更甚至,如果他很”幸运的”php配置的好:
error_reporting = ~E_NOTIC

他也许永远都沉浸在自己的”整洁”风格中, 看不到任何的NOTICE提示, 也不会意识到, 他这么做, 能损失多少的性能~
来, 我们一起来看看:
good.php:
<?php
   $array = array();
   $i = 0;
   while(++$i < 1000){
       $array['good'] = 2;
   }
?>

bad.php:
<?php
   $array = array();
   $i = 0;
   while(++$i < 1000){
       $array[good] = 2;
   }
?>

分别看运行时间(多次平均时间):
加引号的:
$ time php -f good.php
real 0m0.013s
user 0m0.005s
sys 0m0.007

不加引号的:
$ time php -f bad.php
PHP Notice: Use of undefined constant bad - assumed 'bad' in /home/huixinchen/tmp/bad.php
on line (此处省略999行NOTICE)
real 0m0.100s
user 0m0.020s
sys 0m0.029

看看,差别有多大?
哦, 或许我们应该模拟一下那些”幸运的”人们的情况, 去掉花费在记录NOTICE的开销, 看看~
$ time php -f bad.php
real 0m0.037s
user 0m0.018s
sys 0m0.018

我们可以看出, 基本上, 使用引号,和不使用引号的效率损失在3倍以上
那么, 这些效率损失到哪里去了呢?
我们分别看下, 俩个文件生成的OPCODE序列:
good.php :
filename: /home/huixinchen/tmp/good.php
compiled vars: !0 = $array, !1 = $i
line # op fetch ext return operands
-------------------------------------------------------------------------------
   2 0 INIT_ARRAY ~0
         1 ASSIGN !0, ~0
   3 2 ASSIGN !1, 0
   4 3 PRE_INC $3 !1
         4 IS_SMALLER ~4 $3, 1000
         5 JMPZ ~4, ->9
   5 6 ZEND_ASSIGN_DIM !0, 'good'
         7 ZEND_OP_DATA 2, $6
   6 8 JMP ->3
   8 9 RETURN 1
        10* ZEND_HANDLE_EXCEPTIO

bad.php :
filename: /home/huixinchen/tmp/bad.php
compiled vars: !0 = $array, !1 = $i
line # op fetch ext return operands
-------------------------------------------------------------------------------
   2 0 INIT_ARRAY ~0
         1 ASSIGN !0, ~0
   3 2 ASSIGN !1, 0
   4 3 PRE_INC $3 !1
         4 IS_SMALLER ~4 $3, 1000
         5 JMPZ ~4, ->10
   5 6 FETCH_CONSTANT ~5 'bad'
         7 ZEND_ASSIGN_DIM !0, ~5
         8 ZEND_OP_DATA 2, $7
   6 9 JMP ->3
   8 10 RETURN 1
        11* ZEND_HANDLE_EXCEPTIO

我们可以看出(其实,根据NOTICE的提示也知道), PHP会把没有引号引起来的键名当作是常量去获取, 当找不到的时候, 抛出一个NOTICE, 然后再根据”常量明”生成一个字符串, 然后再讲这个字符串做为键名继续~
聪明的你一定会想到, 可能会出现如下不可预期的错误:
define('key_name' , 'laruence');
....
//省略很多行代码
$array[key_name] = 2; //变成了 $array['laruence'] = 2;
//这样的错误, 你会很郁闷吧?

明白了么? 数组中的非数字键的键名一定要有引号啊~
哦, 还记得有人会说, 那在字符串变量替换的时候, 写引号会导致错误,
恩, 标准写法:
$string = "variable value is {$array['key']}"

我很赞同:”be lazy”, 但是, lazy也是应该有原则的.
最后, 好的代码,不应该通过关闭error_reporting来伪装.
附注, FETCH_CONSTANT OPCODE中找不到常量的相关逻辑:
....
if (!zend_get_constant(opline->op2.u.constant.value.str.val,
     opline->op2.u.constant.value.str.len, &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
       zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
                opline->op2.u.constant.value.str.val,
                opline->op2.u.constant.value.str.val);
       EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant;//获取"常量"名字符串
       zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);//分配空间,生成字符串
}
....
PHP 相关文章推荐
PHP持久连接mysql_pconnect()函数使用介绍
Feb 05 PHP
PHP执行批量mysql语句的解决方法
May 02 PHP
PHP中time(),date(),mktime()区别介绍
Sep 28 PHP
ThinkPHP实现非标准名称数据表快速创建模型的方法
Nov 29 PHP
php将HTML表格每行每列转为数组实现采集表格数据的方法
Apr 03 PHP
PHP生成静态HTML页面最简单方法示例
Apr 09 PHP
php实现在多维数组中查找特定value的方法
Jul 29 PHP
详细解读PHP的Yii框架中登陆功能的实现
Aug 21 PHP
PHP+ajax分页实例简析
Dec 07 PHP
简单解析PHP程序的运行流程
Jun 23 PHP
用php和jQuery来实现“顶”和“踩”的投票功能
Oct 13 PHP
php 实现银联商务H5支付的示例代码
Oct 12 PHP
php防注入及开发安全详细解析
Aug 09 #PHP
分割GBK中文遭遇乱码的解决方法
Aug 09 #PHP
解析isset与is_null的区别
Aug 09 #PHP
PHP中怎样保持SESSION不过期 原理及方案介绍
Aug 08 #PHP
php中用socket模拟http中post或者get提交数据的示例代码
Aug 08 #PHP
浅析php变量作用域的一些问题
Aug 08 #PHP
解析php开发中的中文编码问题
Aug 08 #PHP
You might like
c#中的实现php中的preg_replace
2009/12/21 PHP
php 模拟GMAIL,HOTMAIL(MSN),YAHOO,163,126邮箱登录的详细介绍
2013/06/18 PHP
php获取qq用户昵称和在线状态(实例分析)
2013/10/27 PHP
php使用curl和正则表达式抓取网页数据示例
2014/04/13 PHP
PHP实现对图片的反色处理功能【测试可用】
2018/02/01 PHP
创建一个复制UBB软件信息的链接或按钮的js代码
2008/01/06 Javascript
chrome浏览器不支持onmouseleave事件的解决技巧
2013/05/31 Javascript
Jquery基础之事件操作详解
2016/06/14 Javascript
深入理解React中es6创建组件this的方法
2016/08/29 Javascript
Node.js中process模块常用的属性和方法
2016/12/13 Javascript
javascript中数组(Array)对象和字符串(String)对象的常用方法总结
2016/12/15 Javascript
JS实现Ajax的方法分析
2016/12/20 Javascript
用原生js做单页应用
2017/01/17 Javascript
Vue 2.0 服务端渲染入门介绍
2017/03/29 Javascript
vue实现点击图片放大效果
2017/08/15 Javascript
iframe高度自适应及隐藏滚动条的实例详解
2017/09/29 Javascript
js 根据对象数组中的属性进行排序实现代码
2019/09/12 Javascript
全面解析JavaScript Module模式
2020/07/24 Javascript
[58:37]Serenity vs Fnatic 2018国际邀请赛淘汰赛BO1 8.21
2018/08/22 DOTA
python实现图片批量剪切示例
2014/03/25 Python
python实现翻译word表格小程序
2020/02/27 Python
HTML5本地存储localStorage、sessionStorage基本用法、遍历操作、异常处理等
2014/05/08 HTML / CSS
Mio Skincare美国官网:身体紧致及孕期身体护理
2017/03/05 全球购物
英国最大的正宗复古足球衫制造商和零售商:TOFFS
2018/06/21 全球购物
护士实习自我鉴定
2013/10/22 职场文书
高中生家长会演讲稿
2014/01/14 职场文书
员工廉洁自律承诺书
2014/05/26 职场文书
导师对论文的学术评语
2015/01/04 职场文书
给医院的感谢信
2015/01/21 职场文书
医院党建工作总结2015
2015/05/26 职场文书
荒岛余生观后感
2015/06/09 职场文书
个人催款函范文
2015/06/24 职场文书
校运会通讯稿
2015/07/18 职场文书
升学宴祝酒词
2015/08/11 职场文书
导游词之河姆渡遗址博物馆
2019/10/10 职场文书
使用 Apache Dubbo 实现远程通信(微服务架构)
2022/02/12 Servers