база данных — PHP Mysqli Connection через несколько классов

Итак, я стар для PHP, но большую часть времени я использовал процедурный стиль. Я всегда пытался следовать шаблону MVC, хотя я делал что-то процедурно. Кроме того, я привык к некоторым фреймворкам, таким как CakePHP и CodeIgniter. Тем не менее, я еще ничего не делал с нуля, используя ООП. Сегодня я делал это для работы в колледже, и я получил несколько вопросов.

Обычно в рамках мы просто делаем $this->database->query(), на любом контроллере класса, и это работает. По процедурному $link В базу данных входит глобальная область, так что вам не о чем беспокоиться. Я искал способ сделать это с каждым классом в моем коде, но безуспешно. Лучшее, что я мог получить, это использовать класс Singleton для создания экземпляра базы данных, однако мне нужно было получить ссылку на базу данных в каждом отдельном классе. Так, например, в классе Users я должен был бы получить его в конструкторе, и в классе Main, и в любом другом.

Мои вопросы довольно просты. Как использовать ссылку на соединение с базой данных через несколько классов, без необходимости создания экземпляров БД во всех них.
И, если это лучший способ проще, есть ли другой способ сделать это, кроме метода Singleton?

я использую Mysqli lib, кстати.

Вот класс, который я использовал.

class DB extends Mysqli {
protected static $instance;

private function __construct() {
global $config;

parent::__construct($config['db']['host'], $config['db']['user'], $config['db']['password'], $config['db']['database']);

if($this->connect_error)
die('Connect Error ('. $mysqli->connect_errno .') '. $mysqli->connect_error);
}

public static function getInstance() {
if( !self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
}

Вот пример использования класса.

class Main {
protected $db;

public function __construct() {
$this->db = DB::getInstance(); // <-- having to do that in every class is the problem
}

protected function start() {
$this->db->query(something...); // works
}
}

0

Решение

Если вы создаете суперкласс с помощью волшебного метода __get, вы можете проверить, является ли имя запрошенного свойства db, и если да, то автоматически получить экземпляр из вашего класса DB и, если нет, вывести ошибку, как обычно:

<?php
class Super
{
public function __get($name)
{
if($name=="db") {
return DB::getInstance();
} else {
trigger_error("Undefined property", E_USER_NOTICE);
}
}
}
?>
0

Другие решения

Лучше подход будет использовать внедрение зависимости вместо инициирования соединения в каждом классе:

$db = DB::getInstance(); // or any other way to initiate it
$obj1 = new MyClass1($db);
$obj2 = new MyClass2($db);

Таким образом, вы всегда решаете, какую БД вы хотите передать каждому классу. Кроме того, это дает некоторые преимущества, если вы также проводите модульное тестирование — тогда вы можете протестировать каждый класс, предоставив ссылку на тестовую БД или даже посмеявшись над ней.

1

Итак, я придумал свой ответ. Я не уверен, что это оптимальный путь, но вот он.
Используя тот же класс БД, что и в вопросе, я создал «Супер» класс для «удержания» ссылки на базу данных при конструировании. Таким образом, до тех пор, пока я не использую конструктор в других классах, я могу расширить класс «Super» и получить доступ к $this->db без необходимости определять его в каждом классе. Если конструктор действительно нужен, я могу позвонить parent::__construct() от этого, и это будет работать так же.

class Super {
protected $db;

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

class Main extends Super {

/* No constructor,
otherwise it will overwrite the Super
constructor and lack what we've done there. */

public function start() {
$this->db->query(something...); // works
}

}

Я также ввел некоторые другие переменные и функции, которые были необходимы в нескольких классах. Оттуда я могу выбрать, где расширить или нет класс «Супер», когда это необходимо.

0
По вопросам рекламы [email protected]