数据库类设计

时间:2012-03-04 16:59:31

标签: php mysql oop

我正在创建一个包含用户,Smarty模板控件等各种类的Web应用程序。

我已经拥有了一个非常好的数据库类,但我关注它的性能。

目前,在另一个类中,我正在$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个单独的连接。

我想知道在我的应用程序中使用和管理数据库类的最佳方法。我的四个想法是这些:

  1. 使用MySQL服务器的持久连接会解决这个多重连接问题吗?
  2. 我应该使用静态工厂类并返回数据库实例而不是使用new DB()
  3. 使用完全静态的类是正确的解决方案,每次引用它时只做DB::query()(例如)吗?
  4. 我经常在另一个类中使用多个类(因此我们可能有类Folders,它需要User,DB和Smarty类)。通常的做法是以某种方式extend每个班级吗?

4 个答案:

答案 0 :(得分:2)

如果使变量保持连接静态,则可以检查是否已建立连接。静态变量在类的所有实例中都是相同的,因此您可以创建100个全部使用相同连接的实例。你只需要静态引用它:self :: $ dbh而不是$ this-> dbh。

class DB {
    private static $dbh = null;

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

答案 1 :(得分:1)

我建议你查看$ this - >首先是db,然后才创建它。

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

答案 2 :(得分:0)

您需要为您的类注入数据库连接,而不是创建新连接。

// 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,Zend_Registry是一个很好的解决方案,如果你喜欢它http://framework.zend.com/manual/en/zend.registry.using.html

答案 3 :(得分:-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 ((!@ereg('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');
        }
    }

}