У меня есть уровень абстракции базы данных, который начинается с базового класса, например:

class DB {
  function DB() {
    $this->host = "xxx";
    $this->db = "xxx";
    $this->user = "xx";
    $this->pass = "xx";
    $this->dbh = mysql_connect($this->host, $this->user, $this->pass);
    mysql_select_db($this->db);
    // etc
  }
}

class DBI extends DB {
  // etc
}

Теперь я хотел бы, чтобы дочерние классы унаследовали дескриптор базы данных, но не учетные данные. Я пробовал (в классе DBI):

    function DBI (){ 
        $this->host ='';
        $this->db ='';
        $this->user ='';
        $this->pass ='';
    }

Но это убивает ручку; не знаю почему. Также пробовал:

class DBI extends DB {
    var $host ='';
    var $db ='';
    var $user ='';
    var $pass ='';
}

Безрезультатно.

Поэтому мне интересно, должен ли я просто переместить соединение с базой данных из класса altoghether? Просто запустите файл класса с подключением и оставьте все как есть?

Мнения ?

0
jerrygarciuh 3 Сен 2009 в 20:30

4 ответа

Лучший ответ

В конце концов, самый простой подход - просто убрать соединение из классов. Если я начну файл класса с подключением, то дескриптор будет доступен для всех классов, не делая $ dbh атрибутом класса.

0
jerrygarciuh 12 Сен 2009 в 06:03

Тогда не делайте их переменными-членами

<?php
class DB
{
  var $dbh;

  function DB()
  {
    $this->dbh = mysql_connect( "xxx", "xxx", "xx" );
    mysql_select_db( "xx", $this->dbh );
    // etc
  }
}

class DBI extends DB {
  // etc
}

Или переключитесь на PHP5 и сделайте их приватными

<?php
class DB
{
  private
      $host = "xxx"
    , $db   = "xxx"
    , $user = "xx"
    , $pass = "xx"
  ;

  protected $dbh;

  public function __construct()
  {
    $this->dbh = mysql_connect($this->host, $this->user, $this->pass);
    mysql_select_db( $this->db, $this->dbh );
    // etc
  }
}

class DBI extends DB {
  // etc
}

И мне не следует, что вам нужно помнить, что вы передаете свой дескриптор соединения таким функциям, как mysql_select_db (), чтобы остаться безопасность с несколькими подключениями.

РЕДАКТИРОВАТЬ!

Но это убивает ручку; не знаю почему.

Поскольку PHP не выполняет каскадирование конструкторов (конструктор родительского класса не вызывается неявно). Это означает, что DB::DB() не вызывается автоматически при создании экземпляра DBI. Так что вы должны сделать это явно. Думаю, это еще один вариант, но он мне не очень нравится.

class DBI extends DB
{
  function DBI()
  {
    // Call the parent constructor
    parent::DB();

    // Now empty these member variables
    $this->host = '';
    $this->db   = '';
    $this->user = '';
    $this->pass = '';
  }
}
3
Peter Bailey 3 Сен 2009 в 20:45

Почему бы не передать настройки базы данных через конструктор:

function DB($host, $db, $user, $pass) {
    $this->host = $host;
    $this->db = $db;
    $this->user = $user;
    $this->pass = $pass;
    $this->dbh = mysql_connect($this->host, $this->user, $this->pass);
    mysql_select_db($this->db);
}

Тогда ты можешь сделать

function DBI() {
    parent::DB('xxx', 'xxx', 'xxx', 'xxx');
}

(И в PHP4, и в PHP5 родительский конструктор не будет вызываться неявно. Вот почему ваш дескриптор "убит" в вашем подклассе DBI; он никогда не инициализируется. Что вам действительно нужно все же перейти на PHP5 :)

2
Øystein Riiser Gundersen 3 Сен 2009 в 21:05

Если вы не хотите, чтобы дочерний класс наследовал свойство, вы можете объявить его частным. Это работает только для PHP 5:

class DB {

  private $host = "xxx";
  private $db = "xxx";
  private $user = "xx";
  private $pass = "xx";

  function DB() {
    $this->dbh = mysql_connect($this->host, $this->user, $this->pass);
    mysql_select_db($this->db);
    // etc
  }
}

Однако я бы не рекомендовал такой подход. Настройки базы данных лучше хранить в файле конфигурации. Таким образом, проще повторно использовать ваш код между приложениями.

По-прежнему очень часто можно сделать переменную конфигурации массивом внутри файла с именем config.php, а затем использовать этот массив как глобальный в функциях, которые этого требуют. Однако также рекомендуется по возможности держаться подальше от глобальных переменных. Есть несколько хороших схем управления классом конфигурации, например Zend_Config. Вы можете почерпнуть несколько хороших идей из того, как они это сделали.

1
zombat 3 Сен 2009 в 20:38
Когда я делаю это таким образом и выгружаю дочерний объект, я все равно получаю значения, только что помеченные как частные: Incentive Object ([table] => members_incentivesV2 [changedVals] => Array () [connectionError] => [host: private] = > xxx [db: private] => xxx [user: private] => xxx [pass: private] => xxx [dbh] => идентификатор ресурса # 4)
 – 
jerrygarciuh
3 Сен 2009 в 20:51
Не путайте вывод var_dump с фактической видимостью членов класса. Да, данные есть, но экземпляры DBI не могут читать переменные, объявленные как частные в DB
 – 
Peter Bailey
3 Сен 2009 в 20:55