Передача объекта $ db другим классам, чтобы они могли обращаться к базе данных - PullRequest
5 голосов
/ 06 марта 2011

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

$db = new Database($dbConfig);

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

$params = array('username' => $username);
$result = $db->preparedSelect('select password, salt from users where username = :username', $params);

Который копирует результаты оператора PDO в новый ассоциированный массив и возвращает только результаты базы данных обратно на вызывающую страницу. Я перебираю их с помощью простого foreach, например, так:

foreach ($result as $key => $val)
{
   $password = $val['password'];
   $salt = $val['salt'];
}

Хорошо, допустим, я хочу, чтобы другой класс использовал мой объект $ db, чтобы он мог обращаться к базе данных в некоторых методах. На данный момент другой класс выглядит так:

class General
{
    // Database object
    private $db;

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

Это хорошо работает, но мне просто интересно, должен ли конструктор выглядеть так:

public function __construct(&$db)
{
    $this->db = $db;
}

Это должно означать, что я передаю его по ссылке, а не копирую объект в другой класс. Мне не нужна копия объекта $ db внутри класса, я хочу, чтобы он использовал существующий объект базы данных, чтобы у меня не было нескольких его копий, использующих память.

Есть ли разница в PHP5 между передачей его как $ db или & $ db? После некоторого чтения PHP5 по умолчанию передает объекты по ссылке, и другие люди говорят, что теперь делают это по-Java, а некоторые говорят, что использование & делает жесткую ссылку, какой бы она ни была. Я не совсем понимаю. Какой лучший способ сделать это?

Большое спасибо!

Ответы [ 3 ]

8 голосов
/ 06 марта 2011

Есть разница, но на самом деле это не та разница, о которой вы можете подумать.

В PHP5 "$ db", содержащий объект, в основном эквивалентен "Foo *" в C или C ++.Другими словами, $ db не хранит весь объект, он просто хранит небольшой токен, который позволяет коду найти объект при необходимости.Когда вы передаете этот токен по значению, это происходит так же быстро, как и передача целочисленного значения, а не копии всего объекта.Но если вы назначите $ db, это не изменит значение в вызывающей стороне, потому что вы изменяете локальную переменную, содержащую токен, чтобы содержать другой токен.

Если функция принимает "& $ db",это в основном эквивалент передачи «Foo **» в C, или, точнее, функции, принимающей «Foo * &» в C ++.Вызов такой же быстрый, поскольку передается тот же размер, но внутри функции, если вы присваиваете $ db, он изменит значение $ db в вызывающей программе, потому что переменная «передача по ссылке» указывает вам на памятьместоположение, содержащее токен в вызывающей стороне.

Лучший способ сделать это - передать по значению (не используйте "&"), если вы не знаете, что делаете и почему вы это делаете.

3 голосов
/ 06 марта 2011

Это было бы неплохо для статических методов.Вот как много фреймворков выполняют одну и ту же задачу.

class DB
{
   private static $db = FALSE:

   public static function init($dbConfig)
   {
      if(! self:$db)
      {
         self::$db = new Database($dbConfig);
      }
   }

   public static function preparedSelect($sql, $params)
   {
      if(! self::$db)
      {
         die("call the init method first");
      }

      // db stuff, where you would call $this->db call self::$db
   }
}

Так что в других ваших классах, где вы хотите делать вызовы в базу данных, все, что вам нужно сделать, это:

class General
{
   public function __construct()
   {
      DB::init($dbConfig);
   }

   public function someMethod()
   {
      $params = array('username' => $username);
      $result = DB::preparedSelect('select password, salt from users where username = :username', $params);

   }
}
3 голосов
/ 06 марта 2011

Хороший вопрос.

Вы всегда можете выполнить тест, открыв дескриптор $ db, передав его в функцию и проверив их с помощью оператора ===, чтобы убедиться, что это один и тот же объект..

...