2013-01-11 67 views
2

我有一個使用PDO的DB包裝類,並且在構造函數中創建了一個PDO對象。包裝類在我們的命名空間中,我們正在使用自動加載器。問題是在我們的命名空間中找不到PDO類,所以我嘗試使用如here所述的全局名稱空間。全局名稱空間中的PHP使用類

//Class file 
namespace Company\Common; 
class DB { 
    private function __construct(){ 
     $this->Handle=new PDO(...); 
    } 
} 

有了這個,我得到這個(如預期):

Warning: require(...\vendors\Company\Common\PDO.class.php): failed to open stream 

如果我這樣做:

namespace Company\Common; 
use PDO; 

我得到這個:

Fatal error: Class 'DB' not found in ...\includes\utils.php 

而且utils的.php包含在錯誤行中,在實現前工作正常NG命名空間:

DB::getInstance(); 

或者我嘗試這樣做:

namespace Company\Common; 
class DB { 
    private function __construct(){ 
     $this->Handle=new \PDO(...); 
    } 
} 

哪個試圖加載我們的命名空間中的PDO類,因爲它本來是。

我怎樣才能解決這個問題?我想通過做use PDOnew \PDO它會加載全球PDO類,但它似乎並沒有工作?

+1

在什麼命名空間是PDO類? – shadyyx

+0

你在哪裏調用DB類? '使用\ PDO;'是正確的,問題是其他。 –

+0

@shadyyx PDO類是PDO庫中的全局PDO類。 –

回答

0

解決它。我沒有意識到命名空間的別名僅適用於當前文件,而不是任何將來包含的文件。在PHP.net上發現這也適用於別名:

導入規則是以文件爲基礎的,這意味着包含的文件不會繼承父文件的導入規則。

0

通常在我們的項目我們也設置有這樣的路徑:

set_include_path('PATH_TO_GLOBAL_LIBS; PATH_TO_LIBRARY_1; PATH_TO_LIBRARY_X; PATH_TO_DOCUMENT_ROOT'); 

通過這一點,我們告訴PHP(Apache)的搜索應該由自動加載包含任何類這些路徑。

然後假設我們有一些Library_1/var/www/Libs/library_1與此路徑添加到include_path中我們可以這樣做:

namespace Company\Common; 

Class DB { 
    private function __construct() { 
     $this->Handle = new \Library_1(); 
    } 
} 

這應該是相同

namespace Company\Common; 

use \Library_1; 

Class DB { 
    private function __construct() { 
     $this->Handle = new Library_1(); 
    } 
} 
+0

這是所有執行命名空間之前工作的罰款。我已經使用自動加載器來加載所有這些。 include_path仍然是一個問題呢? –

0

這工作,你的問題是別的。

的index.php

<?php 
include('_db.php'); 
use Company\Common\DB; 
new DB; 

_db.php

<?php 
namespace Company\Common; 
use \PDO; 

class DB { 
    public function __construct() { 
     $this->Handle = new PDO; 
    } 
} 
+0

我發現的唯一的事情是,如果我註冊autoloader後做DB ::的getInstance()它工作正常,DB類包括沒有問題,都可以使用。如果我嘗試在utils.php(不是類)中使用DB :: getInstance(),它說它找不到類DB。 –

+0

就像我說的,問題是其他的。聽起來當你utils.php中內沒有裝載的自動加載... –

+0

看起來好像在'使用公司\ COMMON \ DB;'只適用於我用它在文件。如果我有utils.php中內。以及,它工作正常。 'use'聲明僅適用於當前文件,並且不會在整個包含文件中級聯?編輯燁(「導入的規則是每個文件的基礎上,意思包含的文件將不會繼承父文件的導入規則」。) –

0

要訪問像PDODateTime全局對象,你需要用反斜線前綴他們。所以你有兩個選擇。

首先,無論是use您希望在命名空間的類文件中的類:

<?php 
namespace Vendor; 

use \PDO; 
use \PDOException; 

class MyClass 
{ 
    public function __construct() 
    { 
     try { 
      $db = new PDO($dsn, $user, $pass); 
      $db->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); 
     } 
     catch (PDOException $e) { 
      echo $e->getMessage(); 
      exit; 
     } 
    } 
} 

或者只是使用你的類中的反斜槓前綴聲明:

<?php 
namespace Vendor; 

class MyClass 
{ 
    public function __construct() 
    { 
     try { 
      $db = new \PDO($dsn, $user, $pass); 
      $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
     } 
     catch (\PDOException $e) { 
      echo $e->getMessage(); 
      exit; 
     } 
    } 
} 

就個人而言,我更喜歡第一種方法。

4

在名稱空間PHP中,對類的引用必須包含該類的名稱空間,除非您擁有包含該類或其部分名稱空間的use語句。

所以,如果你有這方面沒有use語句,那麼PDO和其他全球性類必須與領先的反斜槓引用的 - 即$obj = new \PDO();

如果你有一個use語句引用類,那麼你可能僅由類名引用它:

use \PDO; 
.... 
$obj = new PDO(); 

如果你引用了很多全球性的類,你會如果你想避免每次使用反斜槓需要use他們每個人的獨立。

相關問題