2012-12-20 27 views
1

我最近升級到PHP 5.3.8到5.3.20。一旦升級很到位,我開始收到大量不能重新聲明錯誤:從PHP 5.3.8升級到5.3.20後,開始接收無法重新聲明類錯誤

class foo { 
    function foo() { 
    global $db; 

    require '/var/www/htdocs/includes/mySQL.php'; 
    $db = new mydb_driver(); 
    } 

    function show_text() { 
    require '/var/www/htdocs/includes/mySQL.php'; 
    $db2 = new mydb_driver(); 
    } 
} 

[20-Dec-2012 11:15:00 America/New_York] PHP Fatal error: Cannot redeclare class user in /var/www/htdocs/includes/mysql.php on line 3

在我的PHP類之一,我使用類似的代碼實例化一個mysql類的構造函數在同一個類中,我創建了一個函數,它使用不同的變量實例化相同的mysql類,以便我可以連接到不同的數據庫。第二個要求是觸發錯誤的原因,我不確定原因。如果我從show_text中刪除require或將其更改爲require_once,它可以正常工作。

有誰知道這兩個版本之間會有什麼變化,會導致此代碼失敗?我甚至不確定如何在沒有require的情況下正確初始化$ db2。是否需要類構造函數使其在文件中全局可見?

編輯: 這不是日誌記錄問題,升級前沒有發生錯誤。這些應用程序工作正常,直到升級。這是我如何在我的錯誤啓用日誌記錄錯誤:

error_reporting = E_ALL & ~E_NOTICE 
+2

您在之前的PHP版本中也遇到了這些錯誤。只是你現在只有啓用了錯誤。 – PeeHaa

+0

您確定在升級之前沒有這樣的錯誤嗎?我不這麼認爲。 –

+0

我的php.ini完全一樣,我沒有收到任何錯誤。 –

回答

4

試試這個

require_once '/var/www/htdocs/includes/mySQL.php'; 

class foo { 
    function foo() { 
    global $db; 

    $db = new mydb_driver(); 
    } 

    function show_text() { 
    $db2 = new mydb_driver(); 
    } 
} 

需要屬於在該文件的頂部,雖然速度較慢,require_once將防止文件被要求兩次,給你那個錯誤

不能真的假設知道你在做什麼。但是你可以切換到這樣的事情太多,擺脫全局和限制更多的PSR標準

require_once '/var/www/htdocs/includes/mySQL.php'; 

class foo { 
    private $db; 

    public function __construct() 
    { 
     $this->db = new mydb_driver(); 
    } 
    public function bar() { 
     // Do bar stuff with $this->db 
    } 

    public function show_text() { 
     // Doo show_text stuff with $this->db 
    } 
} 
+0

謝謝。仍然不知道爲什麼發生這種情況,但這有助於確定我應該如何包括我的文件。謝謝! –

+0

沒問題,很高興我能幫到 – Ascherer

2

在你的類,更改requirerequire_once。這可以確保文件最多隻能加載一次。

+0

雖然文件不是隻包含在構造函數的作用域中嗎?爲什麼show_text函數可以看到它已經包含在內? –

+0

您的示例中沒有構造函數作用域 – Ascherer

+0

@Ascherer在上面的示例中,函數foo()的構造函數不是? From http://php.net/manual/en/language.oop5.decon.php「爲了向後兼容,如果PHP 5找不到給定類的__construct()函數,它將搜索舊式構造函數,有效地,這意味着唯一會遇到兼容性問題的情況是該類有一個名爲__construct()的方法,它被用於不同的語義。「 –

2

您在之前的PHP版本中也遇到了這些錯誤。只是你現在只能啓用錯誤(這是你在開發環境中應該始終做的事)。您只能一次「加載」課程。當您要將其部署到產品環境時,您仍然應該啓用錯誤,但只記錄它們而不顯示它們。

啓用錯誤報告,你可以這樣做:

error_reporting(-1); // or you could do `E_ALL` in PHP 5.4 
ini_set("display_errors", 1); 

你也應該停止使用global關鍵字。這是不好的做法,因爲你不可能測試你的代碼,引入緊密耦合,並可能引入不可預知的結果。

class foo { 
    private $db; 

    public function __construct($db) { 
     $this->db = $db; 
    } 

    public function foo() { 
     $this->db->doSomething(); 
    } 

    public function show_text() { 
     $this->db->doSomething(); 
    } 
} 

require '/var/www/htdocs/includes/mySQL.php'; 
$db = new Mydb_driver(); 
$foo = new Foo($db); 

注:我還增加了知名度,你的方法(public)。儘管默認情況下它們是公開的,但添加它總是更好,所以人們不會認爲這是一個錯誤。

您可能還需要讀入autoloading your classes /這阻止你做require_*include_*和朋友,所以它有助於保持你的代碼乾淨,防止錯誤忘記加載的類時,也將避免這樣的錯誤,你現在得到。

+0

他還可以使用'require_once'來確保類只加載一次。 – EmCo

+0

@EmCo他當然可以。我從來沒有說過他不能。只是在某些代碼中唯一需要的'require_ *','include_ *'需要自動加載器。 – PeeHaa

+0

@PeeHaa @PeeHaa不幸的是,一個自動加載器可能很難在一個已經完成的項目上實現,而這個項目在@Ascherer所依賴的情況下是無法實現的 – Ascherer

相關問題