php - CakePHP 3 中的 MVC - 模型和 View 之间的关注点分离

标签 php cakephp model-view-controller cakephp-3.0

这是一个关于 MVC 的一般问题,但上下文是 CakePHP。

Cake 文档很大程度上避免讨论模型相关代码(例如查询)的最佳放置。也许是为了简单起见,或者为了避免对开发人员如何构建应用程序强加任何想法,他们只是总是将查询记录在 Controller 中。本质上是胖 Controller 模式。

例如

该页面需要 4 个大型查询才能在 View “XYZ”中显示不同区域的数据。查询的最终结果是一组非常具体的数据,仅适用于 View XYZ。

脂肪 Controller

  • Controller 处理请求
  • Controller 在模型 1 上运行查询
  • Controller 在模型 2 上运行查询
  • Controller 在模型 3 上运行查询
  • Controller 在模型 4 上运行查询
  • Controller 对数据执行附加逻辑
  • Controller 发送数据以查看 XYZ

在这种情况下, Controller 正在完成所有工作,并且只是利用 Cake 的内置模型框架功能来查询正确的表。模型层本身不包含自定义代码。

因此,替代方案是使用胖模型模式,但我觉得这也不正确,特别是在模型确定将哪些数据发送到 View 的情况下。

胖模型

  • Controller 处理请求
  • Controller 调用模型 1 来检索数据
  • 模型 1 查询数据并执行附加逻辑,发送回 Controller
  • Controller 调用模型 2 来检索数据
  • 模型 2 查询数据并执行附加逻辑,发送回 Controller
  • Controller 调用模型 3 ...
  • Controller 调用模型 4 ...
  • Controller 发送数据以查看 XYZ

这使 Controller 保持整洁,它仅用于处理请求,委托(delegate)检索所需的数据,然后将其转发到 View 。

对我来说,这个问题是模型层(可能在表类中)现在包含非常具体的查询,这些查询检索专门针对 View XYZ 格式化的数据。如果我想更改 View XYZ 中显示的数据,我可以通过修改返回 View 所需字段的方法来在模型层中进行这些更改。

这似乎是错误的,并导致大型模型因大量非常具体的功能而变得臃肿。


问题

  • 哪种方法更好?
  • 是否有第三种解决方案可以实现以下关注点分离:

Controller

  • 处理请求
  • 决定 View 需要哪些数据,但将工作委托(delegate)给模型
  • 将数据从模型转发到 View
  • 保持 slim

型号

  • 处理所有业务逻辑和数据库查询
  • 数据库查询逻辑不知道 View 需要什么
  • 对于特定 View 的特定一次性功能不会显得臃肿

是否有另一层可以弥合 Controller 和模型表之间的差距,或者它毫无意义?在蛋糕环境中会是什么样子?表或实体之外的自定义类?我完全理解模型层不仅仅意味着事件记录或数据库查询。

最佳答案

The Cake documentation largely avoids discussing optimal placement of model-related code, such as queries.

这不是必需的,也不是框架有责任教育人们有关设计模式的知识 - 恕我直言。解释了各层及其职责here 。如需了解更多信息,请使用 Google 或阅读 Martin Fowlers 有关设计模式的出版物。

Perhaps for simplicity's sake, or to avoid imposing any ideas on how the developer wants to structure their app,

是的。您可以自由地做任何您想做的事情,但人们至少应该熟悉 MVC、OOP 和一般设计模式的基础知识。框架文档的工作不是教授这些主题。

they simply always document queries as being in the controller. Essentially, a Fat Controller pattern.

“他们”是谁?我确信该文档不会鼓励不良实践或反模式。

The problem with this, for me, is that the model layer (probably in table classes) now contains very specific queries which retrieve data specifically formatted for view XYZ. If I want to change the data shown in view XYZ I make those changes in the model layer by modifying the methods which return the fields the view needs.

你的方法很可能会变得肥胖并且具体。您将无法避免特定的方法(总有一些方法无法通用),但您应该使用许多较小的通用方法来编写它们的功能。一个方法应该始终只做一件事并做好,最好不要超过 80 行。

Cake3 中的自定义查找器是编写查询的好方法:

public function findIndex(Query $query, array $options = [])
    return $query->find('active')->find('index')->find('somethingElse');
}

我们的应用程序中有很多“主动”检查,因此我将主动查找器放入一个特征中,并在需要的地方使用它。另外两个查找器向查询添加其他内容。我将三个发现组合在一起,这些发现可以单独使用,也可以根据需要以不同方式组合。

在您的 Controller 中,只需调用 $query = $this->Articles->find('index'); 并将其传递给您的分页器。

永远不要忘记“模型”描述了一个完整的层而不仅仅是表对象。 Cake2 可能导致经验不足的开发人员可能产生 model == table 的印象。我们在 App\Model 中有几个命名空间,它们与数据库操作完全无关,或者使用表对象来完成任务。

关于php - CakePHP 3 中的 MVC - 模型和 View 之间的关注点分离,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37569369/

相关文章:

php - 获取 Bootstrap 下拉值 OnSubmit

php - 更新到 php 5.4.9 后静态标准错误

java - 带有 MongoDB POST 和 GET 记录的 Spring Controller

python - 在 QTableView 中显示分层模型项的详细信息

mysql - CakePHP:如何计算查找中的 hasMany 记录数?

javascript - 使用 Angular 服务保存常用数据

php - Joomla Infinite Scrolling mysql 分页问题

php - php xpath 中的句子中间通配符

javascript - Dropzone js错误 "Uncaught TypeError: $(...).dropzone is not a function"

mysql - CakePHP 3 - 两个外键链接到同一个表 - 使用了错误的外键