再一次, 不要使用(include/require)_once

来源:互联网 发布:练英语六级听力的软件 编辑:程序博客网 时间:2024/06/05 17:22


·        作者Laruence(   )

·        本文地址http://www.laruence.com/2012/09/12/2765.html

·        转载请注明出处

最近关于apc.include_once_override的去留,我们做了几次讨论, 这个APC的配置项一直一来就没有被很好的实现过.

在这里,我想和大家在此分享下,这个问题的原因, 以及对我们的一些启示.

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

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

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

1.       <?php

2.       set_include_path("/tmp/:/tmp2/");

3.       include_once("2.php");

4.       ?>

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

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

1.       1.尝试解析文件的绝对路径,如果能解析成功, 则检查EG(included_files),存在则返回, 不存在继续

2.       2.打开文件, 得到文件的打开路径(opened path)

3.       3.opened pathEG(included_files)查找,是否存在, 如果存在则返回, 不存在继续

4.       4.编译文件(compile_file)

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

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

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

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

1.       <?php

2.       set_include_path("/tmp");

3.       functiona($arg = array()) {

4.           include_once("b.php");

5.       }

6.        

7.       a();

8.       a();

9.       ?>

然后,我们的b.php放置在”/tmp/b.php”,内容如下:

1.       <?php

2.         class B {}

3.       ?>

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

1.       Fatal error - include() : Cannot redeclare class b

(后记 2012-09-15 02:07:20:这个APCbug我已经修复#63070)

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

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

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

 

0 0
原创粉丝点击