【问题标题】:Which Code Should Go Where in MVC Structure哪个代码应该放在 MVC 结构中的哪个位置
【发布时间】:2010-05-07 03:58:58
【问题描述】:

我的问题出在模型和控制器之间。当我将 MVC 仅用于 crud(创建、读取、更新、删除)时,一切对我来说都很完美。我为每个数据库表都有单独的模型。我从控制器访问这些模型, 把它们弄脏。例如,在联系人应用程序中,我在控制器(联系人)中有操作(创建、读取、更新、删除)来使用模型的(联系人)方法(创建、读取、更新、删除)。

当我尝试做一些更复杂的事情时,问题就开始了。有一些复杂的过程,我不知道我应该把它们放在哪里。

  1. 例如,在注册用户进程中。我不能只在用户模型中完成这个过程,因为我还必须使用其他模型(发送邮件,通过其他模型为用户创建其他记录)并通过其他模型进行大量复杂的验证。
  2. 例如,在一些复杂的搜索过程中,我必须访问大量模型(文章、视频、图像等)
  3. 或者,有时,我必须使用 api 来决定我接下来要做什么,或者我将使用哪个数据库模型来记录数据

那么在哪里可以做这个复杂的过程。我不想在控制器中执行它们,因为有时我也应该在其他控制器中使用这些进程。而且我不想将这些过程放在模型中,因为我使用模型作为数据库访问层。可能是我错了,我想知道。谢谢您的回答 。

【问题讨论】:

    标签: php model-view-controller design-patterns frameworks model


    【解决方案1】:

    只是一个简短的评论(没有解决方案)AFAIK,这是一个永恒的问题 - MVC 只是一种模式,因此,理论上可以干净地实现。在实践中,由于可用工具设置的限制(例如编程语言库内容和 UI 组件界面设计..),您必须做出本地决策。重要的是你旨在将这些分开......而不是把所有东西都弄得一团糟。我取消了我的评论,然后看看是否有人有“最终解决方案”。

    【讨论】:

    • 这和generalization 一样好,因为它实际上是在引用实时经验变量——考虑到我在问题海报的位置上令人沮丧。我将不得不抹去 MVC 实现的清洁度系数才能达到我的目标。
    【解决方案2】:

    对于简单的任务,我会编写操作助手(例如 sendNewsletter)。

    对于复杂的任务,我会创建服务(例如电子邮件、身份验证等)。

    【讨论】:

    • 谢谢你的回答,我觉得你的回答和我想的一样,我的意思是我也是这样想的,你能提供任何资源来指导我这种编写代码的方式,或创建 mvc 结构。
    • 如果您喜欢书籍,请阅读Zend Framework 1.8 web application development。对于在线资源,去谷歌搜索“zend framework action helpers”并查看slideshare.net/weierophinney/…(著名的短语:应用程序就像洋葱;)
    【解决方案3】:

    在 MVC 中,您应该将这些东西放在模型中(出于重用的原因)。

    但是,在HVMC 中,您可以将它们放置在任何位置(例如在控制器中)并从您的应用程序中调用控制器。

    【讨论】:

    • 在另一个模型中使用模型怎么样?我可以从另一个模型中调用任何模型吗?谢谢
    • 是的,你可以,我经常在另一个模型中这样做if ($this->userModel->loggedIn()) { }
    • 控制器可以通过 HVMC 模式调用其他控制器。你甚至可以让控制器只在你的应用程序中被调用。通常你检查类似if ($this->request === Request::instance())
    • 在模型中使用像 $_SESSION 这样的超全局变量对我来说似乎很臭。我会在模型中保留与用户注册/登录相关的任何数据库状态更改,但所有会话管理都应该保留在控制器中(或者更可能是从控制器中调用的帮助程序类)
    • @Byron 我仍然不确定我是否以最好的方式做这件事,但它的效果相对较好。为了澄清问题,我通常使用来自 Kohana 的 session library,它是一个简洁的包装器,可以在这里和那里添加一些东西。
    【解决方案4】:

    我会让你的控制器变得简单。

    在许多方面,该模型允许您减轻很多复杂性,否则这些复杂性会遮挡您的控制器代码。正是这种复杂性的划分会让你的代码更容易理解,也更容易维护。

    就我个人而言,我尽量让我的模型类似于现实世界的对象,而不是数据库表或行。如果你让事情以更易读的方式说话,它会变得更容易。一个真实世界的对象可能涉及 5 或 6 个数据库表......当你想要做的只是打开开关、摘一朵花或绘画时,与 5 或 6 个模型交谈将是一个相当大的麻烦一个图标,或发送一条消息。

    【讨论】:

    • @Bingy 你可以参考任何可以指导我的教程吗?即使我喜欢将事物与现实世界相似......请建议
    • 不是在我的脑海中......它的东西将通过实践变得有意义。一旦你做一两次,你就会有一个更好的主意。不要害怕尝试一下。几天或一周后,当你回到它时,你会充满关于如何做得更好的想法。你要避免的是把自己画到一个角落里。例如,让会话数据分布在控制器/模型/和其他处理程序中。由于您为每个表创建了许多模型,因此您可能会从引用许多较小模型的“超级模型”中受益。
    【解决方案5】:

    使用多个模型的控制器有什么问题? MVC 的目的不是让模型可重用吗?在您的第一个场景中,从“注册用户”控制器代码所在的任何位置发送电子邮件和操作其他模型对象都非常好。

    关于您的第二种情况,为什么SearchController 不能使用ArticleModelImageModelVideoModel?有一个没有模型的控制器很好。 SearchController 不需要 SearchModel 类,它只使用其他模型类。

    我尽量不要对 Web 应用程序中的 MVC 大加指责,但基本上,恕我直言,控制器只是完成操作的高级步骤列表。作为一个粗略的例子,“注册用户”控制器代码应该在大约一两行代码中完成以下每个步骤:

    1. 验证输入
      1. 如果无效,请重新显示错误的表单
    2. 从表单输入创建新的UserModel 对象
    3. 将新的UserModel 对象插入数据库中
    4. 创建/编辑任何其他必要的模型对象
    5. 向新用户发送电子邮件
    6. 显示“注册成功”页面

    这些步骤的编码方式很大程度上取决于您使用的框架/架构。

    【讨论】:

    • 为什么我不能使用 Controller 验证数据或执行其他复杂过程的原因有很多。例如,有时我必须从另一个控制器重复此方法,因此我不应该在另一个控制器中重新编写此代码。控制器也不知道所需的验证规则模型,它只提供数据,模型验证这些数据。我不是理解你不必在控制器中验证数据的原因的最佳人选,但我相信你必须不要在控制器中这样做。
    • 模型类是否包含验证函数无关紧要。控制器只需要一个真/假来指示输入是否有效。
    【解决方案6】:

    保持控制器清洁。对于后端处理,请使用 MailManager 等管理器类。

    【讨论】:

      猜你喜欢
      • 2014-02-24
      • 2011-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多