有几种方法可以解决这个问题,首先您可以将系统“集成”到本地系统中,例如 mysqli,或者您可以使用驱动程序从头开始创建自己的系统/结构。
第一种方法有点局限,因为你必须遵守原生 API 的内部结构。
我个人的方法通常是第二种,因为我可以创建一个基于驱动程序的系统,并根据主机操作系统和其他几个因素决定使用什么本机系统。
在为您的应用程序创建数据库 API 以运行您不希望它专门用于该应用程序时,您应该能够获取库并将它们放入一个新项目中,并且一切都应该按预期工作,所以让它摘要是我们必须解决的第一个问题。
下一个障碍是使代码可扩展,编程世界发生了翻天覆地的变化,所以我们应该为变化做好准备,虽然代码只能用几年,但如果我们考虑这么多年并做好准备,那将是有益的.
想象一下,如果下周创建了一个比当前集成到 PHP 中的 mysql(i) 层快 50 倍的新数据库层,您会想尽快切换到该 api,考虑这些因素总是一个好主意在开发阶段。
首先我们应该决定结构,对于传统的抽象层,代码通常都内置在一个大的类文件中,这可能是一种糟糕的编程,因为它应该被分解成它的用途。
我们应该分离类/对象,以便它们执行专门设计的任务。
我们应该有 1 个全局“控制器”,它是主数据库类,它将控制发送到子类和从子类发送的所有操作。
我们将至少为 PHP 5.3 进行设计,所以让我们开始吧:
我倾向于创建一些最终结果的伪代码,这样我就可以了解应该实现什么。
$Connection = new DatabaseConnectionDetails(array(
"hostname" => "localhost",
"username" => "root",
"password" => "n/a",
"charset" => "UTF-8",
"database" => "my_database",
"driver" => "MySQL",
));
$Database = Database::getInstnace($Connection);
$Query = $Database->Query("SELECT * FROM {?:table} WHERE id = {?:id}",array(
"table" => "posts",
"id" => 22
));
if($Query->Execute())
{
$Results = $Query->GetResults();
foreach($Results as $Result)
{
echo $Result->data; //trims, converts to int, returns;
}
}
这就是我想要连接到我的数据库的方式,所以这就是我开始使用基类的方式
class Database
{
private static $_DBInstance;
public static function getInstance(IDatabaseConnectionDetails $ConnectionDetails)
{
if(self::$_DBInstance === null)
{
self::$_DBInstance = new Database($ConnectionDetails);
}
return self::$_DBInstance;
}
public function __construct(IDatabaseConnectionDetails $ConnectionDetails)
{
//We will come back to this.
}
}
查看上面的类,您会看到首先它有一个创建实例(单例),这将有助于在任何应用程序中使用数据库,您还会注意到我专门定义了所需的参数。
在整个抽象层中保持上述因素将使生活变得更加轻松。
让我稍微解释一下目录结构,您必须单独列出以下类
我会选择一个有点像这样的结构:
- 包括
- DBAL
- Database.class.php
- DatabaseConnectionDetails.class.php
- 驱动程序
- 接口
- 结果
如上所述,需要IDatabaseConnectionDetails 接口,这样做的目的是使凭据和主数据库分离,因此IDatabaseConnectionDetails 的主要作用是管理用户凭据。
class DatabaseConnectionDetails implements IDatabaseConnectionDetails
{
public $hostname = "localhost";
public $username = "";
public $password = "";
public $charset = "UTF-8";
public $driver = "mysqli";
public function __construct($params)
{
//Set Params here
}
}
现在上面已经提到了为你的配置创建一个类的好处,类的可扩展性,例如:
class MyCustomConfig extends DatabaseConnectionDetails
{
public $hostname = "host.domain.tld";
public $username = "my_other_user";
public $password = "IJH87b&OTIT8fh";
public $driver = "mssql";
}
当类被接口时,您可以将任何类发送到主数据库对象中,无论是否自定义,因为接口允许您进行扩展。
现在是所需的驱动程序,您应该注意每个驱动程序都应该是驱动程序接口的一部分,这会强制一组方法位于驱动程序本身内。
interface IDatabaseDriver
{
public function setConnectionDetails(IDatabaseConnectionDetails $ConnectionDetails);
public function connect();
public function escape($string);
public function query($string);
/*
all the methods here that will allow the main class can access, such as:
- next()
- prev()
- reset()
ect ect
*/
}
然后,主数据库类将能够根据 $Config->driver 加载正确的驱动程序。
您将在主数据库类中创建模仿典型数据库系统的通用函数,例如fetchObject、fetchArray() 等,然后这些方法将使用驱动程序对象来选择、准备、清理数据,然后返回使用另一个对象/类(例如 QueryResult)的结果将具有一组专用方法,这些方法仅用于遍历结果集。
希望您喜欢这篇长篇文章,但应该让您从头脑中的一个想法开始。
问候:
罗伯特