2011-11-20 87 views
0

我需要在我的課程中使用$GLOBALS['db']$db在我的index.php中定義),但是當我必須調用它時,我不想使用$GLOBALS['db']

我寫了這個代碼在我的課的開頭:

class ClassName 
{ 
    var $db; 

    public function __construct() 
    { 
     $this->db = $GLOBALS['db']; 
    } 

    public function test() 
    { 
     $val = $this->db->oneValue('SELECT first_name FROM users LIMIT 0, 1'); 
     echo $val->first_name; 
    } 
} 

但我不喜歡這一點;我更願意在我的代碼中直接使用$db。有沒有可以通過$db致電$GLOBALS['db']的解決方案?

+5

這是相當反模式。考慮使用IoC/DI:'公共函數__construct($ db){$ this-> db = $ db; }' – knittl

+0

OP並沒有真正解釋爲什麼他必須使用$ GLOBAL,即使是全球性的單身人士也不會那麼邪惡! –

+0

你不喜歡cointructor中的這個單一調用,或者不喜歡$ this-> db而不是$ db? –

回答

8

Simples,只是注入在構造或setter方法:(我假定$ db是這裏的對象,而不是連接參數等的陣列)

class ClassName 
    { 
    protected $db; 

    public function __construct($db) 
    { 
     $this->setConnection($db); 
     //Any other constructor things you want to happen... 
    } 

    /* 
    * This is just here for convenience, this could be protected if you only want to set 
    * the db connection via the constructor 
    */ 
    public function setConnection($db) 
    { 
     $this->db = $db; 
    }  

    public function test() 
    { 
     $val = $this->db->oneValue('SELECT first_name FROM users LIMIT 0, 1'); 
     echo $val->first_name; 
    } 
} 

如在一些評論如上所述,這是一種依賴注入的形式,可以讓您更多地在項目中重用代碼(A Good Thing TM)。

+0

感謝您如此快地回答我的問題。我可以做一些像'class ClassName extends Database'一樣的東西,並在'Database'類中設置連接嗎?例如,我將通過'$ this-> dbOneValue()'來訪問我的函數。這是個好主意嗎? – Yoone

+0

我個人憎恨它每次我想使用它通過構造函數傳遞'$ dbh'參數。 –

+0

你可以讓你的類擴展一個通用的數據庫類,但是當你創建一個新的'ClassName'時,你仍然需要顯式設置'$ db',因爲PHP使用古典繼承,而不是像Javascript那樣的Prototypal。您在通用DB類中創建的所有功能都可以在'ClassName'類中訪問。這有幫助嗎? –

0

我更喜歡使用單例模式的數據庫。

這是我用於我的應用程序的數據庫類。

class Database { 

    protected static $_dbh; 
    const HOST = 'localhost'; 
    const DATABASE = 'dbname'; 
    const USERNAME = 'username'; 
    const PASSWORD = 'password'; 

    private function __construct() { } 

    public static function getInstance() { 
     if(!isset($_dbh)) { 
      try { 
       #Connection String. 
       self::$_dbh = new PDO('mysql:host='.self::HOST.';dbname='.self::DATABASE,self::USERNAME,self::PASSWORD); 
       self::$_dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
      } catch(PDOException $e) { 
       #Print Errors. 
       echo $e->getMessage(); 
      } 
     } 
     return self::$_dbh; 
    } 
} 

因爲我使用單身模式,連接將被重新使用。您現在可以通過調用靜態連接方法在您的應用中的任何地方使用連接,例如

class ClassName 
{ 
    protected static $_dbh; 

    public function __construct() { 
     self::$_dbh = Database::getInstance(); 
    } 

    public function test() { 
     $sth = self::$_dbh->query('SELECT first_name FROM users LIMIT 0, 1'); 
     $row = $sth->fetchAll(PDO::FETCH_ASSOC); 
     echo $row['first_name']; 
    } 
} 
+0

SINGLETON ANTI-PATTERN USAGE ALERT ...這使您無法在不更改代碼的情況下(重新)配置數據庫連接,並且它也限制您只有一個連接(不一定是壞事),除非您複製粘貼到另一個單例類(從而打破DRY)。另外,這意味着您要將數據庫憑證放入源代碼控制中,這應該避免。單元測試也是一場噩夢。 –

+0

@JamesButler:2011年單元測試並不是噩夢,停止返回同樣的舊累的廢話。 –

+0

好的 - 有效的點,它是在「晚期靜態綁定」時代的噩夢,但許多託管公司仍然沒有超越PHP 5.2,我覺得OP很可能受到這種考慮的限制。 –

相關問題