2014-02-17 101 views
6

我一直在使用PHP和MySQL開發一個小型項目。我已經閱讀了很多關於管理連接等方面的最佳實踐。PHP單例數據庫連接模式

我也實現了(在發現周圍的一些帖子後)一個單例類來管理MySQL連接。

require_once 'config.inc.php'; 
class DbConn { 

    private static $instance; 
    private $dbConn; 

    private function __construct() {} 

    /** 
    * 
    * @return DbConn 
    */ 
    private static function getInstance(){ 
     if (self::$instance == null){ 
      $className = __CLASS__; 
      self::$instance = new $className; 
     } 

     return self::$instance; 
    } 

    /** 
    * 
    * @return DbConn 
    */ 
    private static function initConnection(){ 
     $db = self::getInstance(); 
     $connConf = getConfigData(); 
     $db->dbConn = new mysqli($connConf['db_host'], $connConf['db_user'], $connConf['db_pwd'],$connConf['db_name']); 
     $db->dbConn->set_charset('utf8'); 
     return $db; 
    } 

    /** 
    * @return mysqli 
    */ 
    public static function getDbConn() { 
     try { 
      $db = self::initConnection(); 
      return $db->dbConn; 
     } catch (Exception $ex) { 
      echo "I was unable to open a connection to the database. " . $ex->getMessage(); 
      return null; 
     } 
    } 
} 

但是...如果我的網站有一個像10K的遊客同時和我打電話,每次我單身的對象,我應該期待有性能問題?我的意思是,我不應該有一種連接而不是一個單身人士嗎?

+4

什麼是矛盾?您可以將連接設置爲持久,並使用單例。這個模型被用來使得一個請求不會連接兩次到數據庫,但是兩個不同的客戶端會運行你的腳本的兩個不同的實例,所以會使用兩個不同的連接 – mishu

+1

@mishu當然。我多麼愚蠢。謝謝! – LucasM

+0

@mishu:謝謝你解釋它。我們很多人都沒有考慮過這個問題。 – kta

回答

8

在PHP中使用singletons被認爲是不好的做法。根據我的經驗,與他們最成問題的是單元測試。測試單例時很難確保兩個測試是獨立的。

我將代碼約束的責任「只有一個實例應該存在」代碼如何創建Db對象。

此外,它尋找我,因爲你不明白PHP中的單身人士。如果您有10,000個併發請求,那麼每個請求都運行在一個單獨的進程或線程中,這意味着它們都將擁有自己的「單例」實例。

他們在PHP中沒有「連接池」,但可以使用mysqli持久連接。在構建mysqli時,可以通過在主機名前面傳遞p:來實現。這可能有助於在這裏,但小心(meaning read the documentation first)處理它


然而,只是理論,在PHP中的單身必須知道的一個事實,即人可以使用clone。你的情況這意味着它有可能做到這一點:

$db = DB::getInstance(); 
$db2 = clone $db; 

爲了避免這種情況,實現__clone()方法是這樣的:

public function __clone() { 
    throw new Exception("Can't clone a singleton"); 
} 

然而,這只是理論,我會鼓勵你重構這個類並扔掉Singleton模式。

+0

非常感謝。否則你會建議我什麼?我讀了[依賴注入](http://fabien.potencier.org/article/11/what-is-dependency-injection)。乾杯! – LucasM

+0

這與此無關。我只需要執行'$ db = new Db()',然後確保可以從需要它們的所有級別的代碼訪問此實例。 Symfony2正在使用他們的「服務」概念。海事組織這是有道理的,是一個很好的設計方法..(從來沒有想過,它會來的一天,當我談論這個關於symfony :)但我做了,並認爲這是一個很好的實現)...檢查此:http ://symfony.com/doc/current/book/service_container.html – hek2mgl

+0

明白了!再次感謝。乾杯 – LucasM