2012-03-04 94 views
1

我創建各種類的web應用程序的東西,像用戶,Smarty的模板控制等數據庫級的設計

我已經有一個數據庫類,這是一個好主意,但我擔心關於它的表現。

目前,在另一個類,我做$this->db = new DB()創建本地數據庫實例,但該數據庫類的__construct()函數創建到MySQL服務器的新連接我每次做一個新DB()實例時,這顯然是小於明智的。這意味着使用數據庫類的所有不同類的每個實例都會連接到服務器。我沒有大量的課程,但我只希望每頁加載一個課程。

這是我目前所面對的一個精簡樣本:

// Database class used by multiple other classes 
class DB { 
    private $dbh; 

    function __construct() { 
     $this->dbh = // PDO connection here 
    } 

    public function query($str) { 
     // Do a query 
    } 
} 

// Example class User 
class User { 
    private $db; // Stores local instance of DB class. 

    function __construct() { 
     $this->db = new DB(); // Makes a new connection in DB::__construct() 
    } 

    public function login() { 
     $this->db->query('SELECT * FROM users'); 
    } 
} 

我在尋找「最佳」或這樣做的最常見的做法。我不想爲每個頁面加載創建10個單獨的連接。

我想知道用在我的應用程序管理DB類的最佳途徑。我的四個想法是這些:

  1. 使用MySQL服務器的持久連接解決這種多連接問題,我會嗎?
  2. 我應該使用一個靜態工廠類,並返回一個數據庫實例,而不是使用new DB()的?
  3. 是正確的解決方案,使用一個完全靜態類,只是做DB::query()(例如)每一次我引用它的時間?
  4. 我經常在另一個類中使用多個類(所以我們可能需要類文件夾,它需要類User,DB和Smarty)。不知何故,每個班級都有一般練習嗎?extend
+2

你是在正確的軌道,以保持DB作爲一個階級屬性上......這往往是做要麼通過創建,其例如在每類的檢索數據庫中的單需要它,或(也許更好)通過依賴注入,從而實例化數據庫,然後將其作爲參數傳遞給構造函數。 – 2012-03-04 17:02:32

+0

這裏有幾處很好的插圖。如果我找到一個我會鏈接它。 – 2012-03-04 17:04:03

+0

[這裏是一個](http://stackoverflow.com/questions/2017911/properly-using-classes-in-other-classes-in-php)與一個很好的接受答案。還有其他人有多個很好的答案.. – 2012-03-04 17:06:00

回答

2

如果您使變量保持連接靜態,那麼您可以檢查是否已建立連接。靜態變量在類的所有實例中都是相同的,因此您可以創建100個全部使用相同連接的實例。你只需要靜態引用它:self :: $ dbh而不是$ this-> dbh。

class DB { 
    private static $dbh = null; 

    function __construct() { 
     if (is_null(self::$dbh)) { 
      self::$dbh = // PDO connection here 
     } 
    } 
} 
+0

謝謝。我已經創建了我的'$ dbh'靜態,現在我的MySQL日誌只列出了一個打開的連接,然後是頁面的查詢。能夠使用這種快速簡單的解決方案是很好的。 – Bojangles 2012-03-04 18:19:46

0

你需要注入DB連接到您的類,而不是創建一個新的連接。

// In a bootstrap file 
$db = new DB(); 


// User.php 
class User { 
    private $db; 

    function __construct($db=null) { 
     if (!is_null($db)) { 
      $this->setConnection($db); 
     } 
    } 

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

    public function login() { 
     $this->db->query('SELECT * FROM users'); 
    } 
} 

BTW,合適的詞彙是一個很好的解決方案,如果你喜歡它http://framework.zend.com/manual/en/zend.registry.using.html

+0

我應該在我的問題中提到這一點;我不想將任何東西傳遞給構造函數。我需要有一些課程,我通過四,五個不同的課程(如實例),這是不明智的。框架很方便,但我不想在這種情況下使用它。 – Bojangles 2012-03-04 17:07:31

+0

@JamWaffles將對象數組(通過引用發生)傳遞給構造函數怎麼樣?然後從數組中解開類中需要的對象。 – 2012-03-04 17:11:40

+0

已編輯。你可以使用setConnection函數。 IK認爲的最後一個解決方案是使用全局$ db;到每個函數 – dotoree 2012-03-04 17:11:48

1

我建議你檢查$本 - > DB起初,然後只創建它。

function __construct() { 
     if(!isset($this -> db) || !is_a("DB", $this -> db)) { 
     $this->db = new DB(); // Makes a new connection in DB::__construct() 
    } 
} 
-1
<?php 

class DBLayer { 

    public $prefix; 
    public $link_id; 
    public $query_result; 
    public $saved_queries = array(); 
    public $num_queries = 0; 

    public function DBLayer() { 

     $db_prefix = ''; 
     $this->prefix = $db_prefix; 
     if (isset($this->link_id)) { 
      return $this->link_id; 
     } 
     $this->link_id = @mysql_connect(DATABASE_HOST, DATABASE_USER, DATABASE_PASSWORD, true); 

     if ($this->link_id) { 
      if (@mysql_select_db(DATABASE_NAME, $this->link_id)) { 
       return $this->link_id; 
      } else { 
       $this->wplog("Unable to select database. Host:". DATABASE_HOST. "Database:" . DATABASE_NAME . " Error: " . mysql_error(), 'ERROR', __FILE__, __LINE__); 
      } 
     } else { 
      $this->wplog("Unable to connect to MySQL server. Host: " . DATABASE_HOST . " Error: " . mysql_error(), 'ERROR', __FILE__, __LINE__); 
     } 
    } 

    public function query($sql, $unbuffered = false) { 

     if(LOG){echo "<hr>$sql";} 

     $this->query_result = @mysql_query($sql, $this->link_id); 

     if ($this->query_result) { 
      return $this->query_result; 
     } else { 
      $msg= $sql . "<br /> Error: (" . mysql_errno() . ") " . mysql_error(); 
      $this->wplog($msg); 
     } 
    } 

    public function result($query_id = 0, $row = 0) { 
     return ($query_id) ? @mysql_result($query_id, $row) : false; 
    } 

    public function fetch_assoc($query_id = 0) { 
     return ($query_id) ? @mysql_fetch_assoc($query_id) : false; 
    } 

    public function fetch_row($query_id = 0) { 
     return ($query_id) ? @mysql_fetch_row($query_id) : false; 
    } 

    public function num_rows($query_id = 0) { 
     return ($query_id) ? @mysql_num_rows($query_id) : false; 
    } 

    public function affected_rows() { 
     return ($this->link_id) ? @mysql_affected_rows($this->link_id) : false; 
    } 

    public function insert_id() { 
     return ($this->link_id) ? @mysql_insert_id($this->link_id) : false; 
    } 

    public function get_num_queries() { 
     return $this->num_queries; 
    } 

    public function get_saved_queries() { 
     return $this->saved_queries; 
    } 

    public function free_result($query_id = false) { 
     return ($query_id) ? @mysql_free_result($query_id) : false; 
    } 

    public function escape($str) { 
     if (function_exists('mysql_real_escape_string')) 
     return mysql_real_escape_string($str, $this->link_id); 
     else 
     return mysql_escape_string($str); 
    } 

    public function get_select($q, $onlyone=false) { 

     $results = array(); 

     $r = $this->query($q); 

     if ($onlyone) { 
      return $this->fetch_assoc($r); 
     } 
     while ($l = $this->fetch_assoc($r)) { 

      $results[] = $l; 
     } 

     return $results; 
    } 

    public function get_error() { 
     return mysql_error(); 
    } 

    public function close() { 
     if ($this->link_id) { 
      if ($this->query_result) 
      @mysql_free_result($this->query_result); 

      return @mysql_close($this->link_id); 
     } 
     else 
     return false; 
    } 

    public function auto_execute($table, $data, $type, $criteria='') { 

     $result = $this->get_select("desc " . $table); 


     if ($type == "INSERT") 
     $start = "insert into " . $table . " set "; 
     elseif ($type == "UPDATE") 
     $start = "update " . $table . " set "; 
     $sql = $start; 
     foreach ($result as $rst) { 
      foreach ($data as $key => $value) { 
       if ($key == $rst['Field'] and $key !== 0) { 
        if ((@ereg('date', $rst['Type'])) && $value == '') { 
         $sql = $sql . "`".$key."`" . "=NULL, "; 
        } elseif (([email protected]('int', $rst['Type']))) { 
         $sql = $sql . "`".$key."`" . "='" . $value . "', "; 
        } else { 
         if (trim($value) != "") { 
          $sql = $sql . "`".$key."`" . "=" . $value . ", "; 
         } 
        } 
       } 
      } 
     } 

     if ($sql == $start) 
     return 0; 
     else { 
      $sql = substr($sql, 0, strlen($sql) - 2); 
      if ($type == "UPDATE" and !empty($criteria)) 
      $sql = $sql . " where " . $criteria; 
     } 
     //echo $sql;exit; 
     if ($this->query($sql)) { 
      $return = $this->insert_id(); 
     } else { 
      $return = 0; 
     } 
     return $return; 
    } 
    private function wplog($message) { 
     if(LOG==true){ 
      $lineBreak = "\n"; // this function will NOT work on a windows server without further modification 

      $contents = date('Y-m-d H:i:s') . ' ' . $message. $lineBreak; 

      $myFile = SERVER_PATH.'/log.txt'; 
$fh = fopen($myFile, 'a') ; 
fwrite($fh, $contents); 
fclose($fh); 

      //SetFileContents(SERVER_PATH.'/log.txt',$contents,'a'); 
     } 
    } 

} 
+1

我希望你不要在生產中使用它。 – Bojangles 2015-04-18 06:22:34