来自: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[转]的更多相关文章

  1. 请远离include_once和require_once

    尽量使用include, 而不是include_once, 理由是 include_once需要查询一遍已加载的文件列表, 确认是否存在, 然后再加载. 诚然, 这个理由是对的, 不过, 我今天要说的 ...

  2. 深入掌握include_once与require_once的区别

    转:http://www.jb51.net/article/38587.htm  http://www.360doc.com/content/12/1022/17/7851074_243107406. ...

  3. php 中使用include、require、include_once、require_once的区别

    在PHP中,我们经常会通过include.require.include_once.require_once来引用文件,都可以达到引用文件的目的,但他们之间又有哪些区别呢,接一下我们详细的介绍一下 i ...

  4. 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 ...

  5. include、require、include_once和require_once的区别

    /*** * 1.include 和 require 的文件可以有返回值 * 2.include 包含的文件不存在,会发出一个警告,但是不会停止执行代码. * require 在这种情况下会抛出错误并 ...

  6. PHP中include、require、include_once、require_once的区别

    include:使用include引用外部文件时,只有代码执行到include代码段时,调用的外部文件才会被引用并读取,当引用的文件发生错误时,系统只会给出个警告错误,而整个php文件会继续执行.re ...

  7. include,include_once,require,require_once的区别

    1.include() include(/path/to/filename) include()语句将在其被调用的位置处包含一个文件.包含一个文件与在该语句所在位置复制制定文件的数据具有相同内容的效果 ...

  8. 【PHP】- include、require、include_once 和 require_once的区别

    1.include:会将指定的档案读入并且执行里面的程序.      被导入的档案中的程序代码都会被执行,而且这些程序在执行的时候会拥有和源文件中呼叫到 include() 函数的位置相同的变量范围( ...

  9. 初学 Java Web 开发,请远离各种框架,从 Servlet 开发

    Web框架是开发者在使用某种语言编写Web应用服务端时关于架构的最佳实践.很多Web框架是从实际的Web项目抽取出来的,仅和Web的请求和响应处 理有关,形成一个基础,在开发别的应用项目的时候则可以从 ...

随机推荐

  1. Mybatis框架-2

    1.Mybatis中的接口形式 在Mybatis中使用接口形式将通过代理对象调用方法,从而实现sql的执行 1)定义一个接口 package mapper; import java.util.List ...

  2. 洛谷——P2722 总分 Score Inflation(背包)

    P2722 总分 Score Inflation 题目背景 学生在我们USACO的竞赛中的得分越多我们越高兴. 我们试着设计我们的竞赛以便人们能尽可能的多得分,这需要你的帮助 题目描述 我们可以从几个 ...

  3. zabbix报警-邮件-钉钉

    安装zabbix的时候已经配置了zabbix_server的脚本目录 AlertScriptsPath=/opt/app/zabbix/script 所以把邮件.钉钉.微信相关的脚本都放在/opt/z ...

  4. Xamarin Visual Studio不识别JDK路径

    Xamarin Visual Studio不识别JDK路径 错误信息:Cannot find adb.exe in specified SDK path.出现这种情况,是因为Visual Studio ...

  5. Redux 洋葱模型理解

    下面的代码会输出: A middleware1 开始C middleware2 开始E middleware3 开始======= G =======F middleware3 结束D middlew ...

  6. UML对象图、包图

    对象图(Object Diagram)显示了一组对象和他们之间的关系.使用对象图阿狸说明数据结构,类图中的类或组件等实例的快照.对象图和类图一样,反应了系统的静态过程,但它是以实际的或原型化为基础来表 ...

  7. 【BZOJ 1018】【SHOI 2008】堵塞的交通traffic

    http://www.lydsy.com/JudgeOnline/problem.php?id=1018 线段树维护连通性. 把每一列看成一个节点,对于线段树上的每一个节点,维护8个信息,前6个字面意 ...

  8. BZOJ 4443 [Scoi2015]小凸玩矩阵(二分答案+二分图匹配)

    [题目链接]http://www.lydsy.com/JudgeOnline/problem.php?id=4443 [题目大意] 从矩阵中选出N个数,其中任意两个数字不能在同一行或同一列 求选出来的 ...

  9. 【组合计数】UVA - 11538 - Chess Queen

    考虑把皇后放在同一横排或者统一纵列,答案为nm(m-1)和nm(n-1),显然. 考虑同一对角线的情况不妨设,n<=m,对角线从左到右依次为1,2,3,...,n-1,n,n,n,...,n(m ...

  10. view加阴影和边框

    UIImageView *imgvPhoto  = [UIImageView alloc] init]; //添加边框   CALayer *layer = [_imgvPhoto layer];   ...