请远离include_once和require_once[转]
来自:http://www.poluoluo.com/jzxy/201306/216921.html
尽量使用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
排除这些技术因素, 我也一直认为, 我们应该使用include, 而不是include_once, 因为我们完全能做到自己规划, 一个文件只被加载一次. 还可以借助自动加载, 来做到这一点.
你使用include_once, 只能证明, 你对自己的代码没信心.
所以, 建议大家, 不要再使用include_once
请远离include_once和require_once[转]的更多相关文章
- 请远离include_once和require_once
尽量使用include, 而不是include_once, 理由是 include_once需要查询一遍已加载的文件列表, 确认是否存在, 然后再加载. 诚然, 这个理由是对的, 不过, 我今天要说的 ...
- 深入掌握include_once与require_once的区别
转:http://www.jb51.net/article/38587.htm http://www.360doc.com/content/12/1022/17/7851074_243107406. ...
- php 中使用include、require、include_once、require_once的区别
在PHP中,我们经常会通过include.require.include_once.require_once来引用文件,都可以达到引用文件的目的,但他们之间又有哪些区别呢,接一下我们详细的介绍一下 i ...
- php-5.6.26源代码 - include_once、require_once、include、require、eval 的opcode处理器
# ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER 实现在文件 php-\Zend\zend_vm_execute.h static int ZEND_FASTCALL ...
- include、require、include_once和require_once的区别
/*** * 1.include 和 require 的文件可以有返回值 * 2.include 包含的文件不存在,会发出一个警告,但是不会停止执行代码. * require 在这种情况下会抛出错误并 ...
- PHP中include、require、include_once、require_once的区别
include:使用include引用外部文件时,只有代码执行到include代码段时,调用的外部文件才会被引用并读取,当引用的文件发生错误时,系统只会给出个警告错误,而整个php文件会继续执行.re ...
- include,include_once,require,require_once的区别
1.include() include(/path/to/filename) include()语句将在其被调用的位置处包含一个文件.包含一个文件与在该语句所在位置复制制定文件的数据具有相同内容的效果 ...
- 【PHP】- include、require、include_once 和 require_once的区别
1.include:会将指定的档案读入并且执行里面的程序. 被导入的档案中的程序代码都会被执行,而且这些程序在执行的时候会拥有和源文件中呼叫到 include() 函数的位置相同的变量范围( ...
- 初学 Java Web 开发,请远离各种框架,从 Servlet 开发
Web框架是开发者在使用某种语言编写Web应用服务端时关于架构的最佳实践.很多Web框架是从实际的Web项目抽取出来的,仅和Web的请求和响应处 理有关,形成一个基础,在开发别的应用项目的时候则可以从 ...
随机推荐
- 在ns2.35中添加myevalvid框架
在用ns2进行网络视频通信仿真的时候,先要为我们自己的ns2添加evalvid或者myevalvid框架.其中myevalvid框架是由柯志亨老师整合evalvid和ns2之后得出的新框架,笔者建议大 ...
- 设计模式-适配器模式(Adapter Pattern)
本文由@呆代待殆原创,转载请注明出处:http://www.cnblogs.com/coffeeSS/ 适配器模式简介 适配器模式的作用就如同现实生活中转接头的作用一样,现实生活中我们会用USB转接头 ...
- (转)求质数算法的N种境界[1] - 试除法和初级筛法
★引子 前天,俺在<俺的招聘经验[4]:通过笔试答题能看出啥?>一文,以"求质数"作为例子,介绍了一些考察应聘者的经验.由于本文没有政治敏感内容,顺便就转贴到俺在CSD ...
- android View post(Runnable runnable ) 新线程
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha View post(Runnable runnable ) 方法 不会 创建 新线程, ...
- BZOJ 1475 方格取数(二分图最大点权独立集)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1475 [题目大意] 给出一个n*n的方格,从中取一些不相邻的数字,使得和最大 [题解] ...
- 【枚举】【并查集】Gym - 101243F - Vitamins
题意:有n片药,有三种颜色,白色比红色重,红色比蓝色重,给你一些它们之间的重量关系,比如1>3,2=4之类,问你它们的颜色,如果没法判断的输出?. 先并查集把等于号全缩起来,然后按照大于号建图, ...
- 【虚树】hdu6161 Big binary tree
题意:一棵n个结点的完全二叉树,初始i号结点的权值为i.有两种操作:单点修改:询问经过某个结点的路径中,权值和最大的路径的权值和是多少. 修改的时候,暴力修改到根节点的路径上的点的f(x)即可. 跟虚 ...
- 设置Eclipse编码方式
1.windows->Preferences...打开"首选项"对话框,左侧导航树,导航到 general->Workspace,右侧Text file encodin ...
- 基于tiny4412的Linux内核移植 -- eMMC驱动移植(六)
作者信息 作者: 彭东林 邮箱:pengdonglin137@163.com QQ:405728433 平台简介 开发板:tiny4412ADK + S700 + 4GB Flash 要移植的内核版本 ...
- JavaScript基础入门教程(三)
说明 前面的两篇博客介绍了js中的基本知识中的变量类型.标识符等.这篇博客主要谈表达式以及运算符. 原始表达式 原始表达式就是表达式中最小的,不能在分割的表达式,一般指变量.常数直接量.关键字(tru ...