在OOP中编写质量数据模型

时间:2014-10-30 18:44:31

标签: php oop

我很难为我的应用程序编写好的数据模型。我们以人为例说明数据。与Person类相比,我如何对People类进行不可重复但可重复使用的分离?对于这两个类,必须两次定义表(及其连接表)似乎完全错误。

class Person extends CommonModel {
   protected static $table = 'people';
   protected static $join  = array('city' => 'city.id = people.city_id');

   public function __construct($id) {
      // Initialize stuff
   }

   public function fetch($id) {
      // Return person with id $id
   }

   public function isVeryTall() {
      // Return boolean
   }
}

class People extends CommonModel {
   protected static $table = 'people';
   protected static $join  = array('city' => 'city.id = people.city_id');

   public function __construct($id) {
      // Initialize stuff
   }

   public function fetch() {
      // Return all persons
   }
}

但是如果我将它们加入到一个单独的类中,那么当返回一个人列表时,某些只在单个人的上下文中有意义的方法将是可用的。例如,isVeryTall()方法只有在我代表一个人的对象上调用它时才能真正起作用。但是如果我调用fetchPeople()方法,那么我的isVeryTall()方法将在返回的对象中可用,并且它没有任何意义(实际上它甚至可能无法正常工作)。

class Person extends CommonModel {

   protected static $table = 'people';
   protected static $join  = array('city' => 'city.id = people.city_id');

   public function __construct($id) {
      // Return one person
   }

   public function fetchPeople() {
      // Returns all people 
   }

   public function isVeryTall() {
      // Return boolean
   }
}

另一个问题是,如何实现返回人员列表的方法,以返回人员的对象,而不仅仅是数组?我会手动遍历所有行,然后将它们实例化为对象吗?

public function fetchPeople() {
   $people = $this->fetchAll();
   foreach($people as $id => $person) {
      $people[$id] = new Person($person);
   }
   return $people;
}

2 个答案:

答案 0 :(得分:0)

我不会在您的域类中放置特定于实现的持久性代码(您的数据库内容)。将它们分开。然后你可以有一个Person类来完成你需要的东西。对于Person对象的集合,如果组中需要特定的方法(不与持久性相关),则可以定义新类,或者可以使用其中一种内置集合类型(数组)。

有许多方法可以将持久性(数据库)代码分开。我使用Repository模式。我创建了一个类,其中包含在我的域对象和持久性策略(数据库)之间进行转换所需的方法。方法如:

getPerson(PersonCriteria $pc);
getPeople(PersonCriteria $pc);
savePerson(Person $p);
deletePerson($personID);
etc()...

答案 1 :(得分:0)



您最终要做的是为您需要的许多部件重新创建轮子。来自协会和收藏,解决了最后一个问题。您必须从关联和集合构造数据库查询。您将创建标准库的某些部分,这可能不是您的目标。我会通过梨库查看标准ORM或查看https://github.com/gabordemooij/redbean。其他一些是Doctrine和Propel。

如果您想自己滚动并希望继续第一种方法并设置一个集合类来进行分页,并使用where子句查询更大批量的数据。

那样



    // in a base db class
    // filters would be pagination and pairs to be used in where clause filtering
    public function fetch($filters){
        return $this->query($filters)
    }

    // ... in your child class .. using the existing join and table properties .. I would recommend moving 
    // the associations out into another class but as you can see the details of this can go on and on
    public function fetchPeople($limit = 10, $page = 1) {
        $associations = {'table'=> $this->table, 'join'=>$this->join}
            $people = $this->db->fetch(array('limit'=>$limit,'page'=>$page,$associations);
        foreach($people as $id => $person) {
            $people[$id] = new Person($person);
        }
        return $people;
    }