MVC - 在实际应用中是如何工作的?

4

我读过很多计算器和温度计的琐碎MVC例子,但似乎无法将该模式映射到实际应用中。

假设您有一个更复杂的场景。比如说您有一个需要用户登录后才能添加到购物车的网站购物车。首先,用户看到产品页面(/product/detail),然后点击添加商品(/cart/add/207366)。用户还没有登录,因此需要访问登录页面(/user/login),并且通过智能流程将他们带到购物车视图(/cart/list)。从那里,他们可以链接回原始的产品详细信息页面以继续购物。

假设我们有3个数据库表:users、usercart和products。在这种情况下,哪个是模型?整个流程会被封装到ShoppingCart模型的addProductToCartFlow函数中吗?这似乎有点凌乱,因为它需要访问用户表进行登录/身份验证,并访问产品表将产品详细信息/价格放入购物车。

相反,您是否认为ShoppingCart模型是自包含的,仅处理向购物车添加物品、删除物品等操作?用户登录的“逻辑”将在其他地方检查:也许在控制器本身?这将使控制器非常繁忙,具有相当数量的“业务逻辑”,例如检查用户是否已登录,检查购物车是否为空等,而模型只成为数据库表的漂亮名称。

或者,被登录或注销的事实是UserAuthentication模型的一部分,它处理这些功能。或者也许我们需要一个UserPageState模型来告诉我们用户是否应该在登录页面、购物车页面还是产品详细信息页面上?

在您的意见中,这种情况下最好的MVC设计是什么?


谢谢!我根据你给我的反馈添加了一些示例代码http://pastebin.com/f203e3d31。请看一下,让我知道您对这个设计有什么看法。基本上,PageModel会保持用户应该重定向到哪些页面的堆栈。这样,CartModel中的addItem()可以告诉控制器先登录,然后再回来执行addItem()。您觉得呢? - thorie
3个回答

3
你的模型本质上是业务对象。你将拥有购物车、用户和商品(在大多数情况下,每个客户通常只有一个购物车,但谁说不是呢?)。你将拥有驱动流程的控制器 - 对于 /cart/add/207366 的控制器方法将检查用户是否已授权,并将其传递给 /login 的控制器。登录控制器应该足够聪明,能够向控制器 /cart/add/207366 返回正确的信息,随后该控制器应将商品添加到购物车中。
控制器将调用 Cart.AddItem(),但业务逻辑包含在购物车模型内 - 它可能会查找商品价格、基于用户的优惠折扣等。控制器不知道也不关心这些。控制器需要知道用户是否已登录(如果这对应用程序很重要),因为这影响他们的工作(确定要渲染哪个视图)。他们不需要知道客户是否是首选客户、信用额度是否有限或其他与业务逻辑相关的条件。这一切都由模型处理。

0

在我的简单网站中,每个表都有一个模型。我可以在我的控制器中使用任意数量的模型。在更复杂的示例中,当顾客和购物车未分开时,我有一个模型将其结合起来,并具有了解两个表的方法。

拥有许多模型,非常瘦的控制器和只有HTML的视图。您的控制器应该有很多“if”语句,从控制器获取结果。您的视图可以有“fors”循环和重复结果,但没有其他逻辑。不要在视图之外使用HTML标记。

所以回答您的问题,您可以拥有以下模型

  • 用户[进入用户表]
  • 购物车[进入购物车表]
  • 产品表和用户表]
  • 产品[进入产品表]
  • 订单[用户、购物车和产品表(作为基本简单示例)]
  • PageState-跟踪您网站上的用户状态的模型

您有以下控制器

  • 购物车
  • 用户
  • 产品

控制器可能会很长,但每个操作都是一个小的、具有特定作用的操作。我认为拥有一个包含10个操作的控制器是可以接受的,只要这些操作本身很好且很短。

这些操作调用的模型可能会相当长,并且通常会考虑到业务逻辑。我还使用辅助类来执行不属于业务逻辑但仍然至关重要的任务,例如安全性和验证。

还有一大堆视图。购物车视图、登录框视图、产品摘要视图、产品详细信息视图、每个结账阶段的视图、收据视图、HTML格式电子邮件收据视图、类别列表视图、菜单视图、页脚视图等等。有很多很多视图。

您需要拥有一些应用程序类,使得所有控制器都可以继承它,以便您可以反复执行某些操作。

您提到了PHP,因此您拥有组成模板的视图,但如果您使用ASP,则会有一个主页面来执行部分视图。我不知道您在Ruby或Python中做什么,但它们是类似的。


0

我觉得你对繁忙的控制器的担忧不必担心:那是它们的目的。具有添加动作的购物车控制器将依赖于用户控制器或身份验证助手来查看用户是否已登录。上面两个回复非常准确地捕捉到了这一点。

此外,与其为页面创建另一个模型,我只会使用会话变量或表中的另一个字段。另一个模型只会使事情变得更加复杂,并且实际上并没有表示需要自包含的实体。你什么时候认为需要一个访问过的页面堆栈?它实际上只是用户从哪里转到登录表单的URL字符串,你可以使用会话变量以更少的代码和内存消耗的方式跟踪它。只需要在addItem()中检查是否已登录,如果未登录,则重定向到登录页面并存储当前请求。然后一旦登录,检查是否设置了重定向变量,如果是,则跳转到该页面并重置它。我认为没有比这更复杂的需求。

此外,你的pastebin代码看起来像是CakePHP。做得好。如果可能的话,请利用bake控制台和脚手架代码生成。它为你做了很多工作,只留下了有趣的部分给你。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接