Php 积垢和乌德。如何处理这个问题?

Php 积垢和乌德。如何处理这个问题?,php,mysql,oop,crud,Php,Mysql,Oop,Crud,请残酷地诚实,如果你必须的话,把我的作品撕碎 因此,我正在编写一个我最近制作的小型web应用程序。原因很简单,代码变得非常混乱,我想学习并应用更好的OO设计。这个应用程序应该做的只是简单的CRUD。 我有一个包含3个表的数据库,公司和合作伙伴,它们彼此之间没有任何关系,城市与公司和合作伙伴之间有1:n的关系。非常简单,真的。现在,我有几个问题,我将在我的文章的最后陈述。这里我只想解释一下: 我的第一种方法是创建company、partner和city类,从数据库中获取所有数据集,并从中创建对象:

请残酷地诚实,如果你必须的话,把我的作品撕碎

因此,我正在编写一个我最近制作的小型web应用程序。原因很简单,代码变得非常混乱,我想学习并应用更好的OO设计。这个应用程序应该做的只是简单的CRUD。 我有一个包含3个表的数据库,
公司
合作伙伴
,它们彼此之间没有任何关系,
城市
与公司和合作伙伴之间有1:n的关系。非常简单,真的。现在,我有几个问题,我将在我的文章的最后陈述。这里我只想解释一下:

我的第一种方法是创建company、partner和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_companys
arr_partners
,然后它们保存了这些对象……这样工作很好

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

问题:

  • 有这么大的施工人员(我最大的一个施工人员)不好吗 28个参数

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

  • 无论何时只要从数据库中写入、删除,还是应该只将这些更改应用于对象,然后仅在以后(例如会话结束时)对数据库执行命令,这是很常见的吗

  • 我想像这样的应用程序以前一定做过很多次。这里的正确方法是什么?创建对象、处理对象、将其保存到数据库

  • 我有很多问题,但我想很多问题我都不知道该怎么问


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


非常感谢您抽出时间

你所做的看起来很棒。您可以添加一个中间层,将业务对象映射到数据库(对象关系映射)。有很多对象关系映射api。查看wikipedia列表,查找可用于PHP的构造函数

我认为一个包含28个参数的构造函数太多了,您应该让其他类管理一些属性,这些属性有一些共同点。您应该告诉我们您实例化了什么类型的其他属性,这可以帮助您找到一种方法来创建更常见的对象

我认为您还应该创建一个类来管理操作和数据库,就像带有delete、update等的DBHandler一样。。 在我看来,在调用函数之后直接修改数据库中的元组是很重要的


为什么??因为它可以避免冲突,比如你试图更新一个应该被删除的对象,例如,如果你在最后修改了你的数据库。

你实际上是在编写你自己的ORM。所以,我不会打折换一个已经为你写的。自己滚动的好处是,您可以在编写时了解它是如何工作的。但缺点是其他人可能已经做得更好了。但是假设你想继续

一般建议:记住要把问题分解成越来越简单的部分。每个类应该只执行一个简单的函数。此外,您不必担心缓存更新。。。除非您的数据库可能位于调制解调器远程连接的另一端

具体建议如下:

我会将实体实例类设置为容纳数据,而不是进行大量数据加载。使用其他类和逻辑加载数据。我将只使用实体类的构造函数来填充属于该类(及其子类)的数据

一件简单的事情就是在实体类上使用静态方法来加载和保存数据。例如

class city {

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

    function __construct( $id, $name ) {
        $this->id   = $id;
        $this->name = $name;
    }

    // getters and setters
    ...

    // ---------------------
    // static functions
    // ---------------------

    public static function loadById($cityId) {
        // pull up the city by id
        $retval = new city(row["id"], row["name"]);
        // close db connection
        return $retval;
    }

    public static function loadByCustomerId($customerId) {
        // pull up multiple cities by customer id
        // loop through each row and make a new city object
        // return a hash or array of cities
    }

    public static function update($city) {
        // generate your update statement with $city->values
    }

    // other methods for inserting and deleting cities
    ...
}
因此,现在获取和更新城市的代码如下所示:

// loading city data
$city = city::loadById(1); // returns a city instance
$cities = city::loadByCustomerId(1); // returns an array of city instances

// updating city data
$city->name = "Chicago"; // was "chicago"
city::update($city); // saves the change we made to $city
静态方法并不是实现这一点的最佳方法,但它可以为您指明正确的方向。A会更好,但这超出了这个答案的范围。我发现,在遇到更简单的解决方案的问题之前,我常常看不到像存储库模式这样更复杂的解决方案的优点

  • 这真的很糟糕。在这种情况下,代码完全不可读。你有选择
    • 使用setter(可以在内部添加验证逻辑,更好的可读性,不需要用null填充空字段)
    • 为每个域类提供单独的类生成器(为其他对象占用一些内存)。java示例,希望您能够理解: class CompanyBuilder { private final Company c; public CompanyBuilder() { c = new Company();
      } CompanyBuilder addId(String id){c.id = id;} // id should be package visible and class should be located in the same package with builder CompanyBuilder addName(String name){...} CompanyBuilder addCity(String city){...} Company build(){ return c;} } 类公司生成器{ 私人最终公司c; 上市公司生成器(){ c=新公司();
      } CompanyBuilder addId(字符串id){c.id=id;} //id应该是包可见的,类应该与生成器位于同一个包中 CompanyBuilder地址名(字符串名){…} CompanyBuilder地址城市(字符串城市){…} 公司内部版本(){return c;} }
    • 混合解决方案具有组织链的方法(调试更差,可读性更好)。在java中,将使用以下方法: class Company { ... Company addId(String id){ this.id = id; return this;
      } Company addName(String name){...} ... } Usage: Company c = new Company().addId("1").addName("Name1"); 阶级公司{ ... 公司添加id(字符串id){ this.id=id; 返回此项;
      }
      // 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();
      }