2012-03-04 73 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