我正在使用PHP中的MVC。我没有使用框架,我只是想了解模式。
有时我会看到控制器,例如在这个tutorial中,用模型和视图实例化传递给构造函数,在同一个教程中,视图(这里是'模板')类接受一个控制器构造!
所以我的问题是:
答案 0 :(得分:9)
鉴于MVC在网络上存在许多变化和误解,我投票决定将问题视为非建设性。由于评论范围有限,我将此答案作为社区Wiki提供。
MVC was originally conceived by Trygve Reenskaug for Desktop Environments而不是网络。我们现在看到的主要是某些形式的原始模式的变体,如MVP,HMVC,Model2-MVC等。他们的实现彼此不同,人们花了很多时间来讨论“MVC”究竟是什么或者应该如何实现。
就个人而言,我更喜欢Patterns of Enterprise Application Architecture definition of MVC,它说MVC 将用户界面交互分成三个不同的角色,因为这个定义没有实现的概念。
在书中,福勒指出,最重要的区别是模型与控制器和视图的分离。虽然本书确实涵盖了角色之间的关联,但我认为重点是要理解并关注角色而不是实现。
设计模式是蓝图,而不是详细的原理图。此外,MVC是一种模式语言。它的目标是为项目添加结构/表单。了解角色的用途,然后提出适用于您的项目的实现。
Fowler还有一个冗长的article on GUI architectures covering MVC详细解释了关联和依赖关系,以防你没有这本书。
图片/幻灯片:Architecture the Lost Years (Robert Cecil Martin; 4 Nov 2011)
答案 1 :(得分:3)
如果您有用户输入,您需要知道将它们发送到哪个..到哪个控制器。
我不喜欢我的控制器直接使用模型,因为控制器暴露在“外部世界”,容易受到攻击。 您可以查看服务层模式,数据传输对象模式等。 我喜欢将我的模型隔离在控制器将使用的服务API之后。 如果你需要一本关于模式的好书,你可以找到Martin Fowler的:)
答案 2 :(得分:1)
视图不应该引用控制器(当然不是动作链接)。控制器执行告知的操作并将结果发送到视图。
就我使用MVC而言,我在动作中实例化模型并以这种方式使用它。我不喜欢让我的控制器绑定到模型。通常我使用存储库结构来访问我的模型。在较大的项目中,我在控制器和模型之间有一个服务层。在.net MVC中,我开始使用viewmodels作为应用程序的控制器和MVC部分的实体,而我的服务处理与我的域模型有关的任何事情并返回视图模型。
答案 3 :(得分:1)
由于我已经managed在MVC和PHP的上下文中广泛地撰写关于模型的内容,所以我们只关注三元组的View
和Controller
部分。
正如@Gordon已经提到的那样,我们在网上做的是不是经典的MVC 。这不是可能的反弹。相反,我们提出了原始想法的distinct变体。
除非您使用特别糟糕的MVP实现,否则view
实例是对象,负责表示逻辑。
controller
实例是否需要访问view
取决于您使用的MVC模式。在MVP和MVVM模式中controller
实例从model layer
请求信息并将其传递给view
(通过一些修改或其他标志)。
在Model2模式(稍微接近原始概念)中,view
实例本身能够从model layer
中提取信息。在这种情况下,controller
实例无需访问它。
controller
的实例不应直接从model layer
实例化结构。主要原因有两个:
model layer
的结构初始化很复杂。它们通常要求您从model layer
注入数据库连接,缓存处理程序甚至其他结构。此任务应留给控制器使用的单独的类似工厂的实例(在controller
和view
实例之间共享)。
controller
实例的主要职责应该是更改model layer
的状态。它应该从用户那里获取输入,并在表单中进行翻译,model layer
可以理解。
请注意,model layer
作为一个整体必须完全无知关于view
和controller
个实例。
答案 4 :(得分:1)
根据我的经验,对MVC的确切含义有很多解释。几乎每个人都同意这一点:
他们如何联系并彼此交谈是一个辩论,争论,拳击和圣战的问题。
实际上,控制器通常会加载视图和模型,视图有时会加载模型和控制器,但模型通常不会加载控制器或视图。
为什么视图会加载控制器?假设您实现了一个具有自己的控制器,模型和视图的小部件。您希望在多个位置的多个页面上加载此小组件。最简单的方法是在视图中加载小部件的控制器。
为什么视图会加载模型?也许您编写了控制器,因此可以加载两个或更多视图,并且您不希望为每个非常不同的视图加载不同的模型。所以你只需告诉每个视图加载它自己的模型。
分离角色,但允许最有效的交互,并在逻辑上实现您需要的系统。