MVC - 它在现实世界中如何运作?

时间:2009-04-24 16:00:42

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

我已经阅读了许多计算器和温度计的微不足道的MVC例子,但我似乎无法将模式映射到现实世界的应用程序。

假设您有一个更复杂的场景。假设您有一个网站购物车,要求用户在添加到购物车之前登录。首先,用户看到产品页面(/ product / detail)并点击添加项目(/ cart / add / 207366)。用户尚未登录,因此他们需要访问登录页面(/ user / login),然后熟悉流程,将他们带到购物车视图(/ cart / list)。从那里,他们可以链接回原始产品详细信息页面继续购物。

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

相反,你会说ShoppingCart模型是自包含的,只处理从购物车中添加商品,删除商品等?然后在其他地方检查登录用户的“逻辑”:可能在控制器本身?这将使控制器非常繁忙,具​​有相当多的“业务逻辑”,例如检查用户是否已登录,检查购物车是否为空等等,并且模型只是成为数据库表的漂亮名称。

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

您认为这种情况的最佳MVC设计是什么?

3 个答案:

答案 0 :(得分:3)

您的模型本质上是业务对象。你将拥有ShoppingCarts,用户和物品(在大多数情况下,每个客户可能只有一个购物车,但是谁会说?)。您将拥有驱动流量的控制器 - / cart / add / 207366的控制器方法将检查用户是否已获得授权,如果没有,则将它们传递给控制器​​/ login。登录控制器应足够智能,以便将正确的信息传递回控制器/ cart / add / 207366,然后将该项目添加到购物车。

控制器会调用Cart.AddItem(),但业务逻辑包含在购物车模型中 - 它可能会查找商品的价格,基于用户的首选客户折扣等。控制器不会知道或关心这个。控制器需要知道用户是否已登录(如果这对应用程序很重要),因为这会影响他们的工作(确定要呈现的视图)。他们不需要知道客户是首选,还是信用保留,或者其他任何条件对业务逻辑是否重要。这些都由模特处理。

答案 1 :(得分:0)

我的简单网站中的每个表都有一个模型。我可以在我的控制器中使用任意数量的模型。在更复杂的例子中,客户和购物车没有分开,我有一个模型,将这些模型与知道两个表的方法结合在一起。

您的视图中有许多模型,非常纤薄的控制器和仅HTML。您的控制器应该有很多“if”语句从控制器获得结果。你的观点可以有“fors”循环和重复结果,但没有其他逻辑。除了在您的视图中,没有任何HTML标记。

因此,为了回答您的问题,您可以使用以下模型

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

您有以下控制器

  • 用户
  • 产品

控制器可能很长,但每个动作都很小,具有特定的工作。我认为拥有10个动作的控制器是可以的,只要这些动作很好并且自己很短。

这些操作调用的模型可能相当长,通常会考虑业务逻辑。我还使用辅助类来执行非业务逻辑但仍然很关键的事情。像安全和验证一样思考。

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

您可能希望拥有一些所有控制器都继承的ApplicationClass,这样您就可以一遍又一遍地做些事情。

你提到了php,所以你有构成你的模板的视图,但是如果你做了ASP,你会有一个可以进行部分视图的母版页。我不知道你在Ruby或Python中究竟做了什么,但它是相似的。

答案 2 :(得分:0)

我认为你担心忙碌的控制器不应该担心:这是他们的目的。具有添加操作的购物车控制器将依赖于用户控制器或身份验证帮助程序来查看用户是否已登录。以上两个回复很好地捕获了这一点。

此外,我不会为页面创建另一个模型,而是使用会话变量或表中的其他字段。另一个模型实际上只会使事情变得复杂,并且它实际上并不代表您需要自包含的实体。您何时看到需要访问一堆页面?它实际上只是用户来到登录表单的URL的一串字符串,您可以使用会话变量以更少的代码和内存密集的方式跟踪它。只需使用addItem()检查它是否已登录,如果没有重定向到登录页面并存储当前请求。然后登录后,检查是否设置了重定向变量,如果是,请转到它并重置它。我认为不需要比这更复杂的东西。

此外,看起来你的pastebin代码是CakePHP。好的选择。如果可以,请利用烘焙控制台和脚手架代码生成。它为你做了这么多工作,并为你留下了好东西。