PHP - несколько различных баз данных, внедренный класс зависимости - PullRequest
6 голосов
/ 02 ноября 2011

Последние несколько часов я пытался найти ответ на «лучший», самый логичный и т. Д. Способ написания класса базы данных php для одновременного подключения к одной базе данных postgresql и одной базе данных mysql. Кроме того, я хотел бы принять дизайн Dependency Injection, но я новичок во всей этой концепции.

Пока что я придумал ...

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();
        }
    }

}

Очевидно, что дублированный код нарушает СУХОЙ подход. Я знаю и видел много примеров соединений с несколькими базами данных, но большинство из них имеют дело с одним и тем же драйвером и не предоставляют возможности DI.

Я также должен добавить, что я рассмотрел вопрос о размещении деталей соединения в конструкторе класса Database как ...

$driver = 'mysql';
...
$mysqldb = new Database($driver,$un,$pw,...);

$driver = 'pgsql';
...
$pgsqldb = new Database($driver,$un,$pw,...);

но я не знаю, действительно ли это хорошая идея и насколько хорошо она будет работать с DI.

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

Ответы [ 2 ]

8 голосов
/ 02 ноября 2011

Сначала вы должны создать интерфейс для всех операций с БД.

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);
2 голосов
/ 02 ноября 2011

Чтобы избежать дублирования кода, вы можете расширить абстрактный класс

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 использовать другой драйвер для специфичных для БД методов

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 будут черты, поэтому будет больше подходов, чтобы избежать дублирования кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...