Я потратил последние несколько часов, пытаясь найти ответ на «лучший», самый логичный и т. Д. Способ написать класс базы данных php, чтобы одновременно подключиться к одному столбцу postgresql и одному mysql db. Кроме того, я хотел бы принять дизайн Injection Dependency, но я новичок в этой концепции.
До сих пор я придумал …
class Database { public function PgSqlConnect() { /* Connect to database */ $host = 'localhost'; $dbname = '---'; $user = '---'; $pass = '---'; $timeout = 5; /* seconds */ try { $pgsql_dbh = new PDO("pgsql:host=$host; dbname=$dbname", $user, $pass); $pgsql_dbh->setAttribute( PDO::ATTR_TIMEOUT, $timeout ); $pgsql_dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION ); return $pgsql_dbh; } catch( PDOException $e ) { echo 'Unable to connect to database: ' . $e->getMessage(); } } public function MySqlConnect() { /* Connect to database */ $host = 'localhost'; $dbname = '---'; $user = '---'; $pass = '---'; $timeout = 5; /* seconds */ try { $mysql_dbh = new PDO("mysql:host=$host; dbname=$dbname", $user, $pass); $mysql_dbh->setAttribute( PDO::ATTR_TIMEOUT, $timeout ); $mysql_dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION ); return $mysql_dbh; } catch( PDOException $e ) { echo 'Unable to connect to database: ' . $e->getMessage(); } } }
Очевидно, дублированный код нарушает подход DRY. Я знаю и видел много примеров множественных подключений db, но большинство имеют дело с одним и тем же драйвером и не обеспечивают возможности DI.
Я также должен добавить, что я рассмотрел вопрос о размещении деталей подключения в конструкторе класса базы данных как …
$driver = 'mysql'; ... $mysqldb = new Database($driver,$un,$pw,...); $driver = 'pgsql'; ... $pgsqldb = new Database($driver,$un,$pw,...);
но я не знаю, действительно ли это хорошая идея и насколько хорошо она будет работать с DI.
Большое спасибо!
Сначала вы должны создать интерфейс для всех операций БД.
interface IDatabase { function connect(); function query(); ... }
Затем у вас есть разные классы драйверов, реализующие этот интерфейс
class MySQLDB implements IDatabase { } class PGSQLDB implements IDatabase { }
Таким образом, вы можете легко использовать инъекцию зависимостей.
class Test { private $db; function __construct(IDatabase $db) { $this->db = $db; } }
Вы можете назвать это как:
$mysqldb = new MySQLDB(); $test = new Test($mysqldb); or $pgsqldb = new PGSQLDB(); $test = new Test($pgsqldb);
Чтобы избежать дублирования кода, вы можете расширить абстрактный класс
abstract class AbstractDb { public function connect() { // common code to avoid duplication echo 'connected!'; } abstract public function escapeField(); abstract public function escapeValue(); } class MySQL extends AbstractDb { public function escapeField() { // Db-specific method } public function escapeValue() { // Db-specific method } } $db = new MySQL; $db->connect();
Или используйте композицию, и пусть класс Db использует другой драйвер для db-специфических методов
interface IDriver { public function escapeField(); public function escapeValue(); } class MySQLDriver implements IDriver { public function escapeField() { // Db-specific method } public function escapeValue() { // Db-specific method } } class Db { public function __construct($driver) { $this->driver = $driver; } public function connect() { // common code here ? idk, it's just an example echo 'connect!'; } // this method is db-specific, so we call the driver public function escapeField($field) { return $this->driver->escapeField($field); } public function escapeValue() { // same here } } $db = new Db(new MySQLDriver); $db->connect();
В php 5.4 будут признаки, поэтому будет больше подходов, чтобы избежать дублирования кода.