PHP - 多个不同的数据库依赖注入类

时间:2011-11-02 02:28:41

标签: php database oop dependency-injection

我花了最后几个小时试图找到一个答案,以“最好”,最合乎逻辑的方式编写一个php数据库类,同时连接到一个postgresql数据库和一个mysql数据库。此外,我想采用依赖注入设计,但对整个概念来说还是新手。

到目前为止,我已经提出......

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方法。我知道并且已经看到了许多数据库连接的例子,但大多数处理相同的驱动程序并且不提供DI功能。

我还应该补充一点,我已经考虑将连接细节放在Database类构造函数中......

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

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

但我不知道这是不是一个好主意,也不知道它对DI有多好。

非常感谢!

2 个答案:

答案 0 :(得分:8)

您应首先为所有数据库操作创建一个接口。

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

答案 1 :(得分:2)

为避免重复的代码,您可以扩展抽象类

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中会有特征,因此会有更多的方法来避免代码重复。