Сегодня у меня есть PHP-проект с очень странной структурой классов. Как это:
db_base `-- db_base_ext extends db_base +-- module_1 extends db_base_ext +-- module_2 extends db_base_ext . ... +-- module_N extends db_base_ext `-- db_user extends db_base_ext class_1 `-- submodule_1_1 extends class_1
db_base
подключается к db в __construct()
и имеет некоторые вспомогательные методы.
пример выполнения:
$db = new db_user(); $user = new user($db); unset($db); $db = new module_2();
с$db = new db_user(); $user = new user($db); unset($db); $db = new module_2();
Мне не нравится, что в этом коде мы соединяемся с БД дважды, а вся структура классов не очень хороша.
Как я могу сделать это лучше? Я имею в виду создать только один экземпляр БД и после этой работы с любым классом (соответствующим БД)?
Будет ли образец синглэтона хорош для этого?
Ваша проблема заключается в том, что ваши структуры,
module_2 extends db_base_ext db_user extends db_base_ext submodule_1_1 extends class_1
все они нарушают принцип единой ответственности и принцип замены Лискова .
Как я могу сделать это лучше. Я имею в виду создание только одного экземпляра DB и после этой работы с любым классом (соответствующим БД), возможно?
Запуск зависимости – это путь. Вы должны создать экземпляр одного экземпляра db, и все ваши классы будут иметь один и тот же экземпляр $db
.
final class MySQLPDO extends PDO { public function __construct(array $params) { parent::__construct(sprintf('mysql: host=%s; dbname=%s', $params['host'], $params['database']), $params['username'], $params['password']); $this->setAttribute(parent::MYSQL_ATTR_INIT_COMMAND, 'SET NAMES UTF8'); $this->setAttribute(parent::ATTR_ERRMODE, parent::ERRMODE_EXCEPTION); $this->setAttribute(parent::ATTR_EMULATE_PREPARES, false); $this->setAttribute(parent::ATTR_DEFAULT_FETCH_MODE, parent::FETCH_ASSOC); } } $db = new MySQLPDO(array( 'host' => 'localhost', 'database' => 'foo', 'username' => 'root', 'password' => '', )); $user = new User($db); $module = new Module1($user); $foo = new Foo($db);
Итак, что бы вы получили здесь? Возможность повторного использования и способность тестировать.
Обратите внимание: вам следует избегать синглтона, поскольку они вводят другую форму глобального состояния, что плохо для целей модульного тестирования.
Во-первых, я заметил, что классы в проекте называются как функции. Если проект пытается использовать соглашения об именах PEAR, он должен сделать это правильно.
Вы должны отключить модули от класса db_base_ext
. Если модуль нуждается в доступе к экземпляру базы данных, он может быть предоставлен с использованием аргументов или сеттеров конструктора. Он не должен распространять класс напрямую.
$module = new Module($database);
Вы должны подумать об использовании шаблона singleton для вашего класса DB.
Посмотрите здесь учебник . Он использует PDO для связи, но должен также быть действительным для mysqli или других типов.