我的问题是如何从应用程序的模型层抽象数据库连接?主要关注的是能够轻松地从不同类型的数据库进行更改。也许您从一个平面文件、逗号分隔的数据库开始。然后您想要迁移到 SQL 数据库。然后您决定 LDAP 实现会更好。一个人怎么能轻易地计划这样的事情呢?

举一个简单的例子,假设您有一个具有名字、姓氏和电子邮件的用户。一个非常简单的 PHP 类表示它可能如下所示(请忽略公共实例变量的问题):

<?php

class User {
  public $first;
  public $last;
  public $email;
}

?>

我经常看到人们有一个 DAO 类,其中嵌入了 SQL,如下所示:

<?php

class UserDAO {
  public $id;
  public $fist;
  public $last;
  public $email;

  public function create( &$db ) {
    $sql = "INSERT INTO user VALUES( '$first', '$last', '$email' )";
    $db->query( $sql );
  }
}

?>

我对此类策略的问题是,当您想要更改数据库时,您必须更改每个 DAO 类的创建、更新、加载、删除函数来处理新类型的数据库。即使您有一个程序可以为您自动生成它们(我不是特别喜欢),您也必须编辑该程序才能使其立即运行。

您对如何处理这个问题有什么建议?

我当前的想法是为 DAO 对象创建一个超类,具有自己的创建、删除、更新、加载功能。然而,这些函数将采用 DAO 属性的数组并生成查询本身。通过这种方式,唯一的 SQL 位于 SuperDAO 类中,而不是分散在多个类中。然后,如果您想更改数据库层,则只需更改 SuperDAO 类生成查询的方式即可。优点?缺点?可预见的问题?黄金三镖客?

有帮助吗?

解决方案

使用一个 ORM 是通常提取数据库的首选方式。 PHP实现的一个不完整的列表可在维基

其他提示

您可以使用各种框架,如PDO,PEAR :: MDB2或Zend_Db的,但要在12年内PHP开发的诚实,我从来没有从一种类型的数据存储基础架构过渡到另一个。

其极为罕见,甚至从神似像sqlite的,MySQL的东西去了。如果你没有做更多的事,你就必须要大得多的问题呢。

我想出了一个有趣的概念,允许开发人员创建 与数据库无关 代码,但与 ORM 不同的是 不牺牲性能:

  • 使用简单(如 ORM)
  • 与数据库无关:适用于 SQL、NoSQL、文件等
  • 如果供应商允许,总是优化查询(子选择、映射缩减)

结果是 Agile Data - 数据库访问框架 (详细解释请参见视频)。

使用与数据库无关的代码和敏捷数据解决现实生活中的任务

  1. 开始于 描述商业模式.
  2. 创建持久化驱动程序 $db (数据库连接的一个奇特词),可以是 CSV 文件、SQL 或 LDAP。
  3. 将模型与 $db 并表达你的 Action
  4. 执行 Action

此时,框架将根据数据库的功能确定最佳策略,映射您的字段声明,为您准备和执行查询,这样您就不必编写它们。

代码示例

我的下一个代码片段解决了一个相当复杂的确定问题 我们所有 VIP 客户目前的总债务是多少. 。架构:

enter image description here

接下来是独立于供应商的代码:

$clients = new Model_Client($db);
// Object representing all clients - DataSet

$clients -> addCondition('is_vip', true);
// Now DataSet is limited to VIP clients only

$vip_client_orders = $clients->refSet('Order');
// This DataSet will contain only orders placed by VIP clients

$vip_client_orders->addExpression('item_price')->set(function($model, $query){
    return $model->ref('item_id')->fieldQuery('price');
});
// Defines a new field for a model expressed through relation with Item

$vip_client_orders->addExpression('paid')
  ->set(function($model, $query){
    return $model->ref('Payment')->sum('amount');
});
// Defines another field as sum of related payments

$vip_client_orders->addExpression('due')->set(function($model, $query){
    return $query->expr('{item_price} * {qty} - {paid}');
});
// Defines third field for calculating due

$total_due_payment = $vip_client_orders->sum('due')->getOne();
// Defines and executes "sum" action on our expression across specified data-set

生成的查询如果 $db 是SQL:

select sum(
  (select `price` from `item` where `item`.`id` = `order`.`item_id` )
  * `order`.`qty`
  - (select sum(`payment`.`amount`) `amount` 
     from `payment` where `payment`.`order_id` = `order`.`id` )
) `due` from `order` 
where `order`.`user_id` in (
  select `id` from `user` where `user`.`is_client` = 1 and `user`.`is_vip` = 1 
)

对于其他数据源,执行策略可能会大量加载更多数据,但会一致地工作。

我认为我的方法是抽象数据库的好方法,我正在努力在 MIT 许可下实现它:

https://github.com/atk4/data

您应该看看 PDO库。

  

PDO提供了一种数据访问抽象层,这意味着,您使用的无论哪个数据库中,只要使用相同的函数来发出查询和获取数据。

     

PDO不提供数据库抽象;它不会重写SQL或模拟缺失的功能。如果你需要的功能,您应该使用一个完全成熟的抽象层。

的最佳方法是使用ORM(对象关系映射)库。有很多人对PHP。我个人使用,可以推荐学说ORM (我用它与硅石,这是一个简约PHP框架)的组合。

下面是关于PHP的ORM的StackOverflow的线程在这里你可以找到一些替代品,如果你喜欢:好PHP ORM库中?

这在理论上,而且在声音好所有的情形产生 YAGNI

您会过得更好使用SQL库如 PDO 并没有担心LDAP,直到你那里。

一般来说,如果你要使用一个数据库,那么你的应用程序将使用特定于数据库的“品牌”功能中获益的麻烦,而且将是一个更坚实的应用吧。

这是非常罕见从一个数据库系统移动到另一个。你可能会切实考虑到AA功能价值实现的唯一情况是如果你正在写某种松耦合系统或框架,用于大众消费(如Zend框架或Django的)。

我总是使用ADOdb中喜欢。从我所看到的,它看起来像它能够大大不同平台之间的切换。

http://adodb.sf.net

实际上,解决该主题“在哪里实现数据访问逻辑”的解决方案?不复杂。您需要记住的是,您的模型代码必须与数据访问代码分开。

喜欢:

具有一些业务逻辑的模型层 User::name() 方法

class User 
{
  public $first;
  public $last;
  public $email;
  public function name ()
  {
      return $this->first." ".$this->last;
  }
}

数据访问层:

class Link
{
    $this->connection;
    public function __construct ()
    {
        $this->connection = PDO_Some_Connect_Function();
    }
    public function query ($query)
    {
        PDO_Some_Query ($this->connection, $query);
    }

}

class Database
{
    public $link;
    public function __construct ()
    {
        $this->link = new Link();
    }
    public function query ($query)
    {
        $this->link->query ($query);
    }
}

class Users
{
    public $database;
    public function __construct (&$database)
    {
         $this->database = &$database;
    } 
    public save ($user)
    {
        $this->database->link->query ("INSERT INTO user VALUES( '$user->first', '$user->last', '$user->email' ))";
    }

用法:

$database = new Database();

$users = new Users();

$users->save (new User());

在此示例中,很明显,您始终可以更改数据访问类链接,它将对任何内容运行查询(这意味着您可以在更改链接时将用户保存在任何服务器上)。

同时,您拥有干净的模型层代码,它们独立存在,并且不知道谁在哪里保存其对象。

另外,这里的数据库类似乎是不必要的,但实际上它可以产生一些伟大的想法,例如为一个项目中的许多数据库连接收集一个实例的许​​多链接。

还有一个最简单且全能的单文件框架,称为 数据库文件(http://dbphp.net)它是建立在我在这里描述的模式之上的,甚至可以自动创建表,能够完全控制其标准 sql 字段/表设置,并在每次需要时将数据库结构同步到您的模型。

轴突ORM 自动检测架构中的变化,而不需要你重建你的代码。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top