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


最近關於apc.include_once_override的去留, 咱們作了幾回討論, 這個APC的配置項一直一來就沒有被很好的實現過.php

在這裏, 我想和你們在此分享下, 這個問題的緣由, 以及對咱們的一些啓示.html

關於使用include仍是include_once(如下,都包含require_once), 這個討論很長了, 結論也一直有, 就是儘可能使用include, 而不是include_once, 之前最多的理由的是, include_once須要查詢一遍已加載的文件列表, 確認是否存在, 而後再加載.ide

誠然, 這個理由是對的, 不過, 我今天要說的, 是另一個的緣由.ui

咱們知道, PHP去判斷一個文件是否被加載, 是須要獲得這個文件的opened_path的, 意思是說, 好比:spa

 

<?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」..net

而後, 獲得了這個opened_path之後, PHP去已加載的文件列表去查找, 是否已經包含, 若是沒有包含, 那麼就直接compile, 再也不須要open file了.指針

  1. 1. 嘗試解析文件的絕對路徑, 若是能解析成功, 則檢查EG(included_files), 存在則返回, 不存在繼續
  2. 2. 打開文件, 獲得文件的打開路徑(opened path)
  3. 3. 拿opened path去EG(included_files)查找, 是否存在, 若是存在則返回, 不存在繼續
  4. 4. 編譯文件(compile_file)

這個在大多數狀況下, 不是問題, 然而問題出在當你使用APC的時候…code

在使用APC的時候, APC劫持了compile_file這個編譯文件的指針, 從而直接從cache中獲得編譯結果, 避免了對實際文件的open, 避免了對open的system call.htm

然而, 當你在代碼中使用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解決方案.get

可是, 很惋惜, 如我所說, 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
(後記 2012-09-15 02:07:20: 這個APC的bug我已經修復:  #63070 )

 

排除這些技術因素, 我也一直認爲, 咱們應該使用include, 而不是include_once, 由於咱們徹底能作到本身規劃, 一個文件只被加載一次. 還能夠藉助自動加載, 來作到這一點.

你使用include_once, 只能證實, 你對本身的代碼沒信心.

因此, 建議你們, 不要再使用include_once

相關文章
相關標籤/搜索