2012-08-22 91 views
1

我在CodeIgniter驅動的網站中遇到了令人困惑的問題。一個PHP類(TChild)會間歇性地開始拋出「無法重新聲明類」的錯誤,並破壞每個使用它的頁面。我爲了確保聲明代碼只運行一次而花費的時間已經變得非常荒謬,但無濟於事。 tchild.php的頂部目前看起來是這樣的:PHP/Codeigniter無法重新聲明類 - require_once和class_exists失敗了我

(!(isset($GLOBALS['tchild_counter']))) 
    ? $GLOBALS['tchild_counter'] = 1 
    : $GLOBALS['tchild_counter']++ ; 
log_message("info", "tchild has been included " . $GLOBALS['tchild_counter'] . " times"); 

if($GLOBALS['tchild_counter'] != 1) { 
    log_message("info", "STOP RUNNING TWICE"); 
} else { 

if (! defined('BASEPATH')) { 
    log_message("error", "BASEPATH not set; no direct script access allowed"); 
    exit('No direct script access allowed'); 
} 
log_message("info", "Basepath is fine, checking if tchild exists (proc".getmypid().")"); 
log_message("info", "why does that last line seem to run twice?"); 
if (! class_exists('TChild')) { 
log_message("info", "TChild does not exist, creating it"); 
if(class_exists('tchild')) { 
    log_message("info", "tchild apparently exists?"); 
} else { 
    log_message("info","okay, I'm extra-sure that tchild doesn't exist"); 
} 

class TChild extends ActiveRecord\Model { 

它的... 東西一個巨大的樁,但至少應該保證年擄只被定義一次,對嗎?那麼,不。大多數情況下,它工作正常,但偶爾服務器會進入一個奇怪的狀態,儘管所有證據相反,TChild被宣佈兩次。從我添加的廣泛的日誌記錄中,我確信tchild.php只包含在一個單獨的require_once中,並且它絕對不會多次進入類定義。 (但是,它確實吐出了兩個「STOP RUNNING TWICE」日誌條目,即使事情運行良好,我也不知道爲什麼,但至少不會破壞任何東西。)

一旦啓動失敗它會在幾分鐘內(通常)繼續打破一切,然後以最初失敗之類的神祕原因解決問題。

我不知道這裏發生了什麼。谷歌搜索導致我嘗試將apc.enabled = 0添加到我的php.ini中,但它在崩潰或性能方面沒有任何區別。 (我不認爲這是能夠開始,但它是值得一試。)

更新:

啊哈,有一個第三方庫,是包括一個需要聲明文件不止一次。我仍然不知道爲什麼班級被重新宣佈,儘管所有的if/else塊我都被宣佈包裝在裏面,但至少事情似乎現在正在工作。

+4

mmmmmmmmmm ...意大利麪條! – Matt

+0

你的'include'和'require'是什麼樣的?它可能不是這個文件。檢查是否錯過了使用引用此文件的'require_once'。 – Matt

+0

在服務器上啓用短打開PHP標記或被設置在其他地方並不總是被稱爲?你是否意外地用這段代碼覆蓋了另一個文件,所以它無意中重新聲明它?一個月前我做過類似的事情,並非常沮喪,認爲這是非常複雜的事情,但只是我是愚蠢的。 – Rooster

回答

0

剛剛返回log_message(「info」,「STOP RUNNING TWICE」)後如何?返回;或退出(0);似乎你的文件不止一次被包含,你永遠不會停止在你的代碼的任何部分。它只是到達class TChild extends ActiveRecord\Model並被再次聲明的部分。

如果我在那裏,你只是做:

if (! defined('BASEPATH')) { 
    log_message("error", "BASEPATH not set; no direct script access allowed"); 
    exit('No direct script access allowed'); 
} 

if (class_exists('TChild') || class_exists('tchild')) { 
    log_message("info", "class already exists returning"); 
    return; // or exit(0); 
} 

class TChild extends ActiveRecord\Model { 
… 

你問我,你應該檢查該文件從除非代碼一些其他的樁,這是難以追查其包括包括在內。但上面的代碼應該足夠了。 您可以使用debug_backtrace來檢查您的文件包含在其他實用程序中的可以是xhprofxdebug