0

如果您要在数据库中创建项目索引......也许是管理员的用户列表......在面向对象的世界中应该如何完成?

以此作为非常基本的例子:

$sql = 'SELECT
            u.id,
            u.name
        FROM
            users AS u
        WHERE
            u.deleted = "0000-00-00 00:00:00"';

echo '<ul>';
foreach ($db->fetch_all($sql) as $row) {
    $url = './edit/?id=' . urlencode($row['id']);
    echo '
        <li><a href="' . html($url) . '">' . html($row['name']) . '</a></li>';
}
echo '<ul>';

请暂时忽略 HTML 与逻辑混在一起的事实(只是尽量保持简短)。

现在一些开发人员似乎认为在 OOP 世界中,应该这样做:

class user {
    private $id;
    public function __construct($id) {
        $this->id = $id;
    }
    public function name_get() {
        return $this->value_get('name');
    }
    public function admin_url_get() {
        return '/admin/user/edit/?id=' . urlencode($this->id);
    }
    public function age_get() {
        // Calculate from $this->value_get('dob'), using date_diff()
    }
    public function address_billing_get() {
        // i.e. copy returned value onto the order object during checkout
    }
    public function address_delivery_get() {
    }
    private function value_get($field) {

        $db = db_get();

        $sql = 'SELECT
                    u.' . $db->escape_field($field) . '
                FROM
                    user AS u
                WHERE
                    u.id = "' . $db->escape($this->id) . '" AND
                    u.deleted = "0000-00-00 00:00:00"';

        if ($row = $db->fetch($sql)) {
            return $row[$field];
        } else {
            exit_with_error('Cannot return "' . $field . '" for user id "' . $this->id . '"');
        }

    }
}

class user_factory {
    static function get_all() {

        $users = array();

        $db = db_get();

        $sql = 'SELECT
                    u.id
                FROM
                    user AS u
                WHERE
                    u.deleted = "0000-00-00 00:00:00"';

        foreach ($db->fetch_all($sql) as $row) {
            $users[] = new user($row['id']);
        }

        return $users;

    }
}

echo '<ul>';
foreach (user_factory::get_all() as $user) {
    echo '
        <li><a href="' . html($user->admin_url_get()) . '">' . html($user->name_get()) . '</a></li>';
}
echo '</ul>';   

这方面的一些变化包括:

  • 使用 ORM,因此您不必编写实际的 SQL(但那是另一天)。

  • 更改用户__construct 方法以执行SELECT * FROM user WHERE id = X,因此无需每次都通过user->value_get() 查找单个值。

  • 让 user_factory::get_all() 方法执行 SELECT * FROM,并将所有值传递到各个用户对象中……我相信这被称为“构建器”模式(而不是工厂)。

对我来说,这一切似乎都非常低效,有许多查询进出数据库......或者获取不需要的数据(SELECT * FROM 并不是一个好主意)。

例如,假设用户表有诸如他们的家庭/账单地址之类的字段(每个作为第 1、2、3 行、城镇、邮政编码等)......姓名。

我还假设工厂/构建器对象也应该能够接受参数进行搜索(例如,管理员正在寻找特定用户,也许在此页面上它还应该在搜索中包含他们的电子邮件地址字段),并且还通过在一个限制中(例如分页,我猜 10,000+ 条记录可能会导致请求超时)。

4

1 回答 1

1

你混淆了很多东西,以至于我感到困惑......在“OOP 世界”中,就像在现实世界中一样,我们在对象中思考。如果我理解正确,您想要完成什么是在数据库中有一个您想要查询用于不同目的的用户列表?

嗯,首先,我们喜欢根据称为关注点分离的原则来组织事物,也就是说,我们将应用程序构建在层/模块等中,每一层都有自己的责任。

因此,持久层处理与存储(数据库)相关的所有内容并公开一种抽象,即一个或多个对象,其目的是将应用程序对象“转换”为数据,反之亦然。

在您的示例中,持久层又名 DAL(数据访问层)将处理表和所有这些。因此,您通常为每个任务创建一个表,然后您有一个方法(这当然是简化的)。

因此,对于您只需要用户列表(id、Name)的情况,您将拥有一个像 GetUsers() 这样的方法(函数),它将发送相关查询并返回一个简单 DTO(数据传输对象)的列表) 将仅包含 ID 和名称。

应用程序将从该方法获取结果并使用它们来构造视图。在 MVC 上下文中,返回的数据将是 View Model,View 使用该数据生成 html。

您提供的 OOP 示例除了 OOP 之外的所有内容,它只是将概念组合得很糟糕的混杂。

ORM 和工厂适用于您实际需要它们的情况,而这个例子太琐碎了。

OOP 的想法是像乐高积木一样设计应用程序:具有精确目的的多个小部件可以组装成更大的组件,这些组件本身可以一起使用来实现应用程序的目的。

于 2013-01-07T15:32:07.003 回答