强烈声明: 不要使用(include/require)_once


Posted in PHP onJune 06, 2013

关于使用include还是include_once(以下,都包含require_once), 这个讨论很长了, 结论也一直有, 就是尽量使用include, 而不是include_once, 以前最多的理由的是, include_once需要查询一遍已加载的文件列表, 确认是否存在, 然后再加载.

诚然, 这个理由是对的, 不过, 我今天要说的, 是另外一个的原因.

我们知道, PHP去判断一个文件是否被加载, 是需要得到这个文件的opened_path的, 意思是说, 比如:

<?php
set_include_path("/tmp/:/tmp2/");
include_once("2.php");
?>

当PHP看到include_once “2.php”的时候, 他并不知道这个文件的实际路径是什么, 也就无法从已加载的文件列表去判断是否已经加载, 所以在include_once的实现中, 会首先尝试解析这个文件的真实路径(对于普通文件这个解析仅仅类似是检查getcwd和文件路径, 所以如果是相对路径, 一般是不会成功), 如果解析成功, 则查找EG(include_files), 如果存在则说明包含过了, 返回, 否则open这个文件, 从而得到这个文件的opened_path. 比如上面的例子, 这个文件存在于 “/tmp2/2.php”.

然后, 得到了这个opened_path以后, PHP去已加载的文件列表去查找, 是否已经包含, 如果没有包含, 那么就直接compile, 不再需要open file了.

1. 尝试解析文件的绝对路径, 如果能解析成功, 则检查EG(included_files), 存在则返回, 不存在继续
2. 打开文件, 得到文件的打开路径(opened path)
3. 拿opened path去EG(included_files)查找, 是否存在, 如果存在则返回, 不存在继续
4. 编译文件(compile_file)

这个在大多数情况下, 不是问题, 然而问题出在当你使用APC的时候…

在使用APC的时候, APC劫持了compile_file这个编译文件的指针, 从而直接从cache中得到编译结果, 避免了对实际文件的open, 避免了对open的system call.

然而, 当你在代码中使用include_once的时候, 在compile_file之前, PHP已经尝试去open file了, 然后才进入被APC劫持的compile file中, 这样一来, 就会产生一次额外的open操作. 而APC正是为了解决这个问题, 引入了include_once_override, 在include_once_override开启的情况下, APC会劫持PHP的ZEND_INCLUDE_OR_EVAL opcode handler, 通过stat来确定文件的绝对路径, 然后如果发现没有被加载, 就改写opcode为include, 做一个tricky解决方案.

但是, 很可惜, 如我所说, APC的include_once_override实现的一直不好, 会有一些未定义的问题, 比如:

<?php
set_include_path("/tmp");
function a($arg = array()) {
    include_once("b.php");
}
a();
a();
?>

然后, 我们的b.php放置在”/tmp/b.php”, 内容如下:
<?php
  class B {}
?>

那么在打开apc.include_once_override的情况下, 连续访问就会得到如下错误:

Fatal error - include() : Cannot redeclare class b

排除这些技术因素, 我也一直认为, 我们应该使用include, 而不是include_once, 因为我们完全能做到自己规划, 一个文件只被加载一次. 还可以借助自动加载, 来做到这一点.

你使用include_once, 只能证明, 你对自己的代码没信心.

所以, 建议大家, 不要再使用include_once

PHP 相关文章推荐
php源码加密 仿微盾PHP加密专家(PHPCodeLock)
May 06 PHP
《PHP编程最快明白》第五讲:php目录、文件操作
Nov 01 PHP
php whois查询API制作方法
Jun 23 PHP
php正则取img标记中任意属性(正则替换去掉或改变图片img标记中的任意属性)
Aug 13 PHP
PHP swfupload图片上传的实例代码
Sep 30 PHP
php图片缩放实现方法
Feb 20 PHP
PHP中功能强大却很少使用的函数实例小结
Nov 10 PHP
PHP实现表单提交数据的验证处理功能【防SQL注入和XSS攻击等】
Jul 21 PHP
使用XHProf查找PHP性能瓶颈的实例
Dec 13 PHP
PHP实现cookie跨域session共享的方法分析
Aug 23 PHP
PHP中通过getopt解析GNU C风格命令行选项
Nov 18 PHP
PHP反射基础知识回顾
Sep 10 PHP
探讨PHP调用时间格式的参数详解
Jun 06 #PHP
探讨多键值cookie(php中cookie存取数组)的详解
Jun 06 #PHP
深入密码加salt原理的分析
Jun 06 #PHP
深入理解PHP几个算法:PHP冒泡、PHP二分法、PHP求素数、PHP乘法表
Jun 06 #PHP
php定时计划任务的实现方法详解
Jun 06 #PHP
PHP使用DES进行加密与解密的方法详解
Jun 06 #PHP
php xml常用函数的集合(比较详细)
Jun 06 #PHP
You might like
迅雷下载《中学科技》怀旧期刊下载
2021/02/27 无线电
对javascript和select部件的结合运用
2006/10/09 PHP
php 三维饼图的实现代码
2008/09/28 PHP
php获取QQ头像并显示的方法
2014/12/23 PHP
ThinkPHP自定义函数解决模板标签加减运算的方法
2015/07/03 PHP
判断是否输入完毕再激活提交按钮
2006/06/26 Javascript
jQuery的三种$()
2009/12/30 Javascript
jquery checkbox全选、取消全选实现代码
2010/03/05 Javascript
js自定义事件及事件交互原理概述(一)
2013/02/01 Javascript
Vue.js基础知识汇总
2016/04/27 Javascript
浅谈Vue响应式(数组变异方法)
2018/05/07 Javascript
详解angular脏检查原理及伪代码实现
2018/06/08 Javascript
JavaScript中为事件指定处理程序的五种方式分析
2018/07/27 Javascript
深入浅析angular和vue还有jquery的区别
2018/08/13 jQuery
vue-cli 使用axios的操作方法及整合axios的多种方法
2018/09/12 Javascript
Mint UI实现A-Z字母排序的城市选择列表
2018/12/28 Javascript
说说如何在Vue.js中实现数字输入组件的方法
2019/01/08 Javascript
js中Generator函数的深入讲解
2019/04/07 Javascript
js实现GIF图片的分解和合成
2019/10/24 Javascript
vuex的使用步骤
2021/01/06 Vue.js
深入理解Python3中的http.client模块
2017/03/29 Python
python实现微信跳一跳辅助工具步骤详解
2018/01/04 Python
详解Python使用tensorflow入门指南
2018/02/09 Python
Python反爬虫技术之防止IP地址被封杀的讲解
2019/01/09 Python
Python根据服务获取端口号的方法
2019/09/25 Python
pytorch::Dataloader中的迭代器和生成器应用详解
2020/01/03 Python
利用PyQt5+Matplotlib 绘制静态/动态图的实现代码
2020/07/13 Python
openCV提取图像中的矩形区域
2020/07/21 Python
惠而浦美国官网:Whirlpool.com
2021/01/19 全球购物
什么是静态路由,其特点是什么?什么是动态路由,其特点是什么?
2013/07/26 面试题
医学生自荐信范文
2013/12/03 职场文书
《识字五》教学反思
2014/03/01 职场文书
教师党员公开承诺事项
2014/05/28 职场文书
小学生2014国庆节演讲稿:祖国在我心中
2014/09/21 职场文书
初三毕业感言
2015/07/31 职场文书
干部外出学习心得体会
2016/01/18 职场文书