php - CRUD 和 OOD。如何解决这个问题?

标签 php mysql oop crud

请诚实一点,必要时拆开我的作品。

所以我正在重新编写我最近制作的一个小型网络应用程序。原因很简单,代码变得非常困惑,我想学习和应用更好的 OO 设计。这个应用程序应该做的只是简单的 CRUD。 我有一个包含 3 个表的数据库,companiespartners 彼此没有关系,city 与公司和合作伙伴。很简单,真的。现在,我有几个问题将在帖子末尾说明。在这里,我将尝试解释一下:

我的第一种方法是创建公司、合作伙伴和城市类,从数据库中获取所有数据集并从中创建对象:

class company {

    private $id   = null;
    private $name = null;
    private $city = null;

    //many more attributes

    function __construct( $id, $name, $city, [...] ) {

        $this->id   = $id;
        $this->name = $name;
        $this->city = $city;

        //huge constructor
    }

   /*
    *  getters + setters here
    *
    *  no need to paste the partner class as it looks just like this one
    *
    */
}

这就是所有这些类所做的。我从数据库中获取每个数据集并构建公司、合作伙伴和城市对象(这些类中的属性城市是一个本身具有多个属性的对象)并将它们保存到两个数组 arr_companiesarr_partners,然后保存这些对象......并且它像那样工作得很好。

现在,我想要的是更新、插入、删除数据库,所有 3 个类(城市、公司、合作伙伴)都需要这个功能。我的方法是创建一个带有构造函数的新类,该构造函数基本上采用 2 个字符串命令和对象,例如('update', 'company') 然后它将直接在数据库中更新公司,而我的对象保持不变。这让我非常难过,因为我拥有如此精美的构造对象,但我不知道如何使用它们。

问题:

  • 拥有如此庞大的构造函数是不是很糟糕(我最大的构造函数需要 28个参数)?

  • 你是否应该为数据库创建一个单独的类 操作还是最好有一个抽象类或 接口(interface)并让子类自己处理更新、删除、插入?

  • 无论何时都只写入、从数据库中删除是否很常见,或者我应该只将这些更改应用到我的对象并且只在以后执行对数据库的命令,例如当 session 结束时?

  • 我想像这样的应用程序以前一定已经完成过很多次了。这里的正确方法是什么?创建对象、使用对象、将它们保存到数据库?

  • 我有很多问题,但我想其中很多我只是不知道如何提出。

请注意,如果可能的话,我现在不想使用 ORM。

非常感谢您的宝贵时间。

最佳答案

OP 中提出的问题:

“拥有如此庞大的构造函数(我最大的构造函数需要 28 个参数)是不是很糟糕”?

  • 是的。想象一下调用代码。您必须传递 28 个不同的值,更不用说每次调用都必须遵守构造函数中指定的确切顺序。如果一个参数不合适,您可能会破坏与参数相关的算法。如果您确实需要传递大量参数,我建议将它们作为数组传递(将 example 发布到另一个 SO 问题)。

“您应该为数据库操作创建一个单独的类,还是为其创建一个抽象类或接口(interface)并让子类自己处理更新、删除、插入更好?”

  • 一般来说,在创建类时,您想尝试找出最能代表您的业务需求的名词。在您的特定情况下,您可能有三个类(class);公司、合作伙伴和城市。

  • 现在在每个类(名词)中,您的方法将采用动词的形式,因此从语义上讲您的调用代码是有意义的:if ($company->getName() === 'forbes' )

  • 正如您提到的,每个类都需要一个数据库对象 (dbo) 才能使用,因此您可以实现任意数量的模式来向您的类公开数据集连接;单例、带工厂的单例或依赖注入(inject)等。

  • 抽象(父)类非常适合在子类之间共享通用算法,应该在您处于设计的伪代码阶段时加以识别。父类还允许您通过在父类中声明抽象方法来强制子类拥有方法。

  • 接口(interface)在某些情况下是一个有用的工具,但我发现它们不如在父类中声明抽象方法灵活。但在类不共享父类的情况下效果很好。

“无论何时都只写入、从数据库中删除是很常见的,还是我应该将这些更改应用到我的对象,并且只在以后执行对数据库的命令,例如在 session 结束时”?

  • CRUD 事件应该在执行操作时发生。例如,如果您等待 session 结束,您可能会遇到 session 因用户关闭浏览器而提前结束的情况。为了更好地保护您的数据,您可以将 CRUD 事件包装在事务中。

  • 如果您正在运行一个高流量应用程序,您可以实现一个排队系统并将要完成的工作排队。

“我想像这样的应用程序以前肯定已经完成了很多次。这里正确的方法是什么?创建对象,使用对象,将它们保存到数据库中”?

  • 你是对的,这在以前就已经完成了,通常被称为 ORM(对象关系映射器)。基本上,ORM 将自省(introspection)您的数据库模式,并创建代表您的模式的对象(和关系)。因此,您不是在使用 native SQL,而是在使用对象。虽然您可以使用 SQL 来满足自定义业务需求,但在 Doctrine 的情况下,您将使用 Doctrine 查询语言 (DQL) 而不是原生 SQL。

  • 我强烈推荐的 ORM 是 Doctrine .

如果您不想使用 ORM,您可以将 CRUD 方法添加到您的主要类中。我选择了一个接口(interface),这样您的类就不必从由数据库操作组成的父类扩展。另外,查看 this post关于使用单例/工厂来公开您的类数据库对象。

考虑以下几点:

// Company.php
class Company implements iDatabaseOperation

    public function delete()
    {
        // Lets use a DBO singleton/factory for DB access
        //   Uses PDO, which is strongly recommended
        $dbo = Database::factory(Database::DATABASE_NAME);

        $dbo->beginTransaction();

        try {

            $sql = 
                "DELETE FROM " .
                "    company " .
                "WHERE " .
                "    id = :companyId " .
                "LIMIT 1";

            $stmt = $dbo->prepare($sql);

            $stmt->bindValue(':companyId', $this->getId());

            $stmt->execute();

            $dbo->commit();

        } catch (Exception $e) {

            $dbo->rollback();

            error_log($e->getMessage();

            $e = null; // Php's garbage collection sucks
        }
    }
}

// iDatabaseOperation.php
interface iDatabaseOperation
{
    public function delete();
    public function update();
    public function insert();
}

关于php - CRUD 和 OOD。如何解决这个问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8825622/

相关文章:

php - MySQL 查询 500 内部服务器错误

PHP:给出警报弹出窗口然后重定向页面

mysql - 日期时间 DATE DIFF 未按预期工作

javascript - 在 JavaScript 中向原语添加元数据

php - 一个困难的一对多mysql查询

mysql - View - 如果在按查询分组的情况下未找到任何行,则返回 0

php - onchange 后下拉选择值重置

java - 对象组合相对于类继承的缺点

php - PDO 错误 : Call to a member function prepare() on null

php - Symfony 2 从实体管理器获取实体的原始数据