Model view controller 真实世界的MVC-处理表单

Model view controller 真实世界的MVC-处理表单,model-view-controller,language-agnostic,design-patterns,Model View Controller,Language Agnostic,Design Patterns,我仍然对MVC应该如何工作有些困惑 假设我有一个出售小部件的网站。我有一个列表页面,/widgets/list和一个产品页面/widgets/product/123 这两种方法都可以使用小部件控制器,并调用列表和产品方法-到目前为止非常简单。假设我还有其他几个控制器,用于各种用途 现在,我在我的标题中添加了一个时事通讯注册框,即在网站的每一页上。 这将如何运作?我的想法是它应该提交给/newsletter/signup 但是如果出现错误(比如你没有正确填写你的电子邮件地址),会发生什么呢?它应该

我仍然对MVC应该如何工作有些困惑

假设我有一个出售小部件的网站。我有一个列表页面,
/widgets/list
和一个产品页面
/widgets/product/123

这两种方法都可以使用
小部件
控制器,并调用
列表
产品
方法-到目前为止非常简单。假设我还有其他几个控制器,用于各种用途

现在,我在我的标题中添加了一个时事通讯注册框,即在网站的每一页上。 这将如何运作?我的想法是它应该提交给
/newsletter/signup

但是如果出现错误(比如你没有正确填写你的电子邮件地址),会发生什么呢?它应该显示您所在的任何页面(例如,
/widgets/list
),但需要运行
时事通讯
控制器。
小部件
控制器不知道
时事通讯
控制器,因此我无法将代码放在那里。。。这是怎么回事

编辑:请不要使用AJAX-我可以更容易地理解这一点。考虑JavaScript被禁用时的后退。

编辑2:任何涉及此类内容的示例或教程都将不胜感激


编辑3:是否允许视图调用操作?例如,标题可能会调用
新闻稿->索引()

,您必须将错误消息放在某个全局位置,页面控制器(包括“分包商”
新闻稿
)可以将其拾取


对于AJAX,您可以让
时事通讯
控制器与
DIV
对话,在该对话框中可以看到它(因为您没有重新加载整个页面)。为此,您需要在AJAX请求完成时调用的页面中使用一段JavaScript,该页面将获取字符串并将其放在您想要的任何位置。

我的MVC体验更实用,而不是“书中所说的”,但下面是:

您将拥有一个基本控制器类(在CakePHP中-这是我最熟悉的-它被称为
AppController
),它是所有其他控制器的子类。这个类将实现您所说的所有“全局”内容

实例:

在我的
AppController
类中,框架定义了一个
beforeFilter()
回调,它基本上是在每次页面加载时执行的。在这里,我会检查注册表是否已经提交,并妥善处理。如果注册过程中出现了一些问题,我会在会话中添加一些内容,指出同样多的问题,我的视图只需检查是否存在来自时事通讯模型的错误列表,如果存在,则显示它们


这可能比你要求的要重一些,理论上要轻一些,但我在这方面没有任何正式的培训,所以我最好:)

在时事通讯表单中添加一个字段,用于存储当前页面的URL。
当在提交时事通讯期间发生错误时,检索URL并重定向到该页面。如果您将错误信息放在正确的位置,那么它应该由新闻稿表单提取,您可以说,新闻稿表单包含在每个页面中。

对于应该返回一些验证错误等的小部件,请使用(或来自MvcContrib的分包商)+AJAX。

我所做的是将每个表单发布到自己身上。在控制器中,我检查post变量是否已设置;如果是,我做验证。如果验证成功,我将重定向到另一个页面。如果失败,表单页面将重新加载错误消息。这样做很容易,并减少了代码重复。请看这里:

**in controller**:

If post variable is set:
    validate form

    if form is validated:
        redirect to new page (or whatever)
    else:
        add error messages to the $data variable of the view
    endif

endif

//$data contains whatever information you'd normally pass to the view.
//if there was a validation error, the messages are added to the $data variable
show view with $data variable

正如您所看到的,流总是通过单视图加载语句完成。但是,如果验证成功,您将被快速转到另一页。

我不明白为什么每页上的新闻通讯框的错误消息必须在同一页中呈现。如果您有一个页面发布到另一个操作-与当前视图完全无关(例如-搜索),则没有理由在原始页面中显示错误消息。您能在同一页上显示成功消息吗?这将在哪里处理

通讯表单的错误消息应显示在专用于通讯的视图中。例如,查看它在Stackoverflow中是如何完成的-进入搜索框并键入nothing,只需按enter键。这是一种错误,因为您没有指定要搜索的内容。Stackoverflow将带您进入另一个页面,解释搜索如何工作


为什么会这样?原因很简单-用户在某个页面上,并选择参与与当前页面无关的活动,因此没有理由将其保留在该页面上。

在提交给/newsletter/signup控制器的页面上添加一个隐藏字段,其中包含控制器完成后的url,即当前页面,如何(也可以使用referer http头)

然后,此控制器将错误消息列表或成功消息添加到视图要呈现的对象列表中,然后再转发到上面的隐藏字段指定的控制器。然后,此控制器添加要在视图中显示的对象列表(例如,小部件列表)


然后,在视图中,您可以显示来自时事通讯控制器(如果存在)的错误消息。

有一个很好的以ASP.net MVC为中心的描述方法,可以在MVC环境中包括小部件(可重用组件)


基本思想是使用自己的请求管道设置小部件,而不是将它们合并成一个组合控制器/视图,这将破坏MVC的可维护性。

如果我有一个现有的网站,其中有10个控制器,每个控制器有5个动作,这不意味着如果我在标题中添加一个时事通讯注册,我就必须编辑50个功能吗这是一个例外