【问题标题】:OOP design: How to incorporate DB handling into application objectsOOP 设计:如何将 DB 处理合并到应用程序对象中
【发布时间】:2011-01-18 18:35:32
【问题描述】:

这是我经常遇到的设计问题,我想找到一些关于该主题的一般见解。此处提供的代码只是一个示例。

在设计阶段很容易决定你需要一个对象:

User
==========
Unique ID
Login name
Password
Full name

而且很容易将其转换为数据库对象:

CREATE TABLE user (
    user_id INT NOT NULL PRIMARY KEY,
    username VARCHAR(15) NOT NULL UNIQUE,
    password_hash CHAR(32) NOT NULL,
    full_name VARCHAR(50)
);

我的疑虑始于 PHP 级别。明显的转换是:

<?php
class User{
    public $user_id, $username, $full_name;
}
?>

但是,我应该如何填写实际值?

我可以保持类与 DB 无关:

<?php
class User{
    public $user_id, $username, $full_name;
    public function __construct($user_id, $username, $full_name){
        $this->user_id = $user_id;
        $this->username = $username;
        $this->full_name = $full_name;
    }
}
?>

但是我需要在其他地方运行查询...

我可以将它封装在类构造函数中:

<?php
class User{
    public $user_id, $username, $full_name;
    public function __construct($user_id){
        $sql = 'SELECT username, full_name FROM user WHERE user_id=?';
        $parameters = array($user_id);
        $res = get_row_from_db($sql, $parameters);

        $this->user_id = $user_id;
        $this->username = $res['username'];
        $this->full_name = $res['username'];
    }
}
?>

这看起来很优雅,但它让我无法在课堂上做很多事情:

  • 通过用户名和密码验证用户($user_id 未知)
  • 打印论坛帖子中的用户信息(我无法承受 100 个查询来显示 100 个用户)

很可能,我需要定义几个类,但我不确定如何组织它。一个基类和多个子类?独立课?具有特定方法的单个类?也许这是一种众所周知的设计模式,但我学过过程式编程。

我也很欣赏以下方面的一些想法:

  • 处理用户集合
  • 在会话中存储信息,因此不需要在每个页面请求上查询数据库

==== 记录====

我已将 Gordon 的回复标记为答案,因为它提供了有趣的阅读。不管怎样,值得注意的是,我在 PHP 手册的 Object Serialization 页面中的一个用户 cmets 中发现了一个very illustrative code snippet,可以总结如下:

  • 它使用一个类。
  • 一个实例代表一个特定的用户。
  • 向构造函数提供用户详细信息。
  • 该类为能够拥有实例之前所需的功能提供静态方法,例如按 ID 或名称从数据库中获取用户。
  • 用户实例可以序列化为会话数据。

不是 OOP 专家,我发现它非常简单但干净且有用。 OOP 文本倾向于使简单的任务过于复杂,而我的日常工作主要是小项目。

【问题讨论】:

  • 您将如何使用第二种方法创建新用户?数据库中不会存在新用户。
  • 你提到的代码 sn-p 在我看来像是 ActiveRecord 模式的实现。

标签: php database oop


【解决方案1】:

这取决于您的架构。四种常见的数据源架构模式可以在Martin FowlerPatterns of Enterprise Application Architecture找到:

  • Table Data Gateway

    充当数据库表网关的对象。一个实例处理表中的所有行。

  • Row Data Gateway

    充当数据源中单个记录的网关的对象。每行有一个实例。

  • Active Record

    在数据库表或视图中包装一行、封装数据库访问并在该数据上添加域逻辑的对象。

  • Data Mapper

    在对象和数据库之间移动数据的映射器层,同时保持它们彼此独立以及映射器本身。

更多模式:

【讨论】:

    【解决方案2】:

    Zend Framework quickstart 有一个非常容易掌握的模型映射器(谷歌术语)的概述,以及一些源代码。

    【讨论】:

      【解决方案3】:

      您是否考虑过使用像 DoctrinePropel 这样的对象关系映射库?

      【讨论】:

      • 并非如此。我希望提高我的设计技能,而不是学习第三方库。
      • 我会质疑在已经存在好的解决方案的领域中提高您的设计技能是否是最有效的改进点。如果您使用不错的第三方库,您可以腾出时间来提高您在第三方解决方案不存在的领域的设计技能。
      • 不过,即使没有框架,我也希望能够编写出好的代码。你知道的那种一般文化。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多