2012-03-04 5 views
1

Я создаю веб-приложение с различными классами для вещей, как пользователь, 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. Я часто использую несколько классов в другом (поэтому у нас могут быть классы Folders, которым требуются классы User, DB и Smarty). Является ли это обычной практикой для extend каждого класса?
+2

Вы находитесь на правильном пути, чтобы сохранить БД как свойство класса ... Это часто делается либо путем создания синглтона для базы данных, чей экземпляр извлекаются в каждом классе необходимости, или (возможно, лучше) путем инъекции зависимостей, посредством чего вы создаете экземпляр БД и затем передаете его в конструктор в качестве параметра. –

+0

Здесь есть несколько хороших иллюстраций. Если я найду его, я свяжу его. –

+0

[Здесь один] (http://stackoverflow.com/questions/2017911/properly-using-classes-in-other-classes-in-php) с хорошим принятым ответом.Есть другие с несколькими хорошими ответами. –

ответ

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

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, Zend_Registry является хорошим решением, если вы предпочитаете это http://framework.zend.com/manual/en/zend.registry.using.html

+0

Я должен был упомянуть об этом в моем вопросе; Я не хочу передавать что-либо в функцию конструктора. Мне нужно иметь несколько классов, в которых я передаю четыре или пять разных классов (как экземпляры), что неудивительно. Рамки удобны, но я не хочу использовать их в этом случае. – Bojangles

+0

@JamWaffles Что касается передачи в массив объектов (что происходит по ссылке) конструкторам? Затем распакуйте, какие объекты нужны внутри класса из массива. –

+0

Отредактировано. Вы можете использовать функцию setConnection. Последнее решение IK - использовать глобальные $ db; каждой функции – dotoree

1

Я хотел бы предложить вам проверить $ это -> дБ на первом, а затем только создать его.

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

Смежные вопросы