模型类是应该表示实体还是返回实体

Mar*_*ner 10 php model-view-controller codeigniter

我正在使用CodeIgniter设计一个Web应用程序(但我认为这个问题通常适用于Web应用程序中的MVC模式).

当我为某个数据库实体设计模型类时(例如,BlogEntry为了说明),我基本上有两个选择:

"经典OOP"方法是让类代表实体,即类的一个实例 BlogEntry.在CodeIgniter中,这将导致类似的代码

class Blogentry extends CI_Model {
    function load($id) {
      // Access database
      $this->id = $dbresult.id;
      $this->title = $dbresult.title;
      $this->author = $dbresult.author;
    }
}
Run Code Online (Sandbox Code Playgroud)

要访问某些博客条目,我会进行$this->load->model('blogentry');调用$this->blogentry->load($id),然后使用模型类实例.

我经常在野外看到的另一种方法是让模型在某些数据结构中返回实体.在代码中:

class Blogentry extends CI_Model {
  function get_entry($id) {
    // Access database, yielding $dbresult
    return $dbresult;
}
Run Code Online (Sandbox Code Playgroud)

有了这个,我会写

$this->load->model('blogentry');
$the_entry = $this->blogentry->get_entry($id);
Run Code Online (Sandbox Code Playgroud)

在控制器中工作$the_entry.在第二种情况下,类更像是工厂构建器类.

这两种方法中的任何一种都被认为是在MVC中做M的"正确方法"吗?我想,我经常看到第二种方法,但我没有看过那么多MVC-Webapps.对于为什么第一种或第二种方法可能更合适的任何想法?

oro*_*kek 12

首先,CodeIgniter 不是 MVC框架.最适合的范例可能是MVP或类似ORM-Template-Adapter的东西.因此,让我根据命名谬误分解我的答案:

在古典/传统的MVC(未哪些框架要求是MVC),模型是不是一个类或者一个文件,而是一个层包含所有领域的业务逻辑,通常只由之类的东西域对象,数据映射器,以及处理调用实体和域逻辑之间的接口的东西,以便将这些代码保持在控制器之外(例如,在MVC中).Tereško将它们命名为"服务",这对于准官方名称来说已经足够了.

因此在传统的MVC中,对模型层的请求通过"服务"进行,然后"服务"与域对象和数据映射器进行交互.

显然,所有这些与CodeIgniter和其他框架称之为"MVC"的内容没什么关系.在这种设计模式中(我简称为"CIMVC"),Model是一个由Controller调用和操作的类,它直接与数据库交互.将数据存储在模型中的成员变量中并不会产生很多语义上的意义,但如果您对类似的东西感兴趣,请查看使用CIMVC编写的任何ORM插件/库.(虽然ORM解决方案在符合传统MVC方面不会更好......)

至于常见做法,我见过的大多数CI应用程序都将"原始"数据库数据返回给控制器进行处理; 这使域业务逻辑保持在模型中.我在CIMVC中的个人偏好是最小化/消除模型中的域业务逻辑.

tl; dr - CodeIgniter中的"传统/适当"MVC基本上是不可能的,所以试图强制你的CI代码符合传统的MVC范式是愚蠢的(并且可能会让你疯狂)

编辑:为了澄清模型层中有关业务逻辑的一些早期混淆,是的,您应该拥有模型层中的所有业务逻辑.但是,如果正在进行额外的数据处理(排序,操纵等),现在我们进入危险区域以防止DRY和SRP; 您希望模型可以重复使用,因此要小心添加如此多的或专门的逻辑,使其在应用程序的其他部分变得无法使用.

  • 不同意模型中很少或没有业务逻辑,这正是业务逻辑应该驻留的位置(胖模型/瘦控制器).这样就可以在需要它的应用程序中的任何地方共享业务逻辑. (2认同)