(Walter.Fan编译自Jason E. Sweat写的An Introduction to MVC Using PHP)
MVC在B/S大行其道的今天,恐怕是设计模式中最为著名的一种啦.
对于website来说,它是一种不错的架构.
所谓MVC即Model-View-Controller模型-视图-控制器,是一种面向对象的设计模式.MVC用类将业务逻辑(数据存储在哪里,哪些用户被准许处理这些数据,如何处理这些数据)放在模型中,表示逻辑(来自模型的数据怎样被表示出来)放在视图中,而将应用程序的整个流程控制放在控制器中.
PS.设计模式是程序员的内功心法,有关的设计模式的九阴真经就是"四人帮"的"Design Patterns". 在http://www.phppattenrs.com上有关于设计模式在PHP中的应用的介绍.
为什么要用MVC?
因为MVC是一种对于website所存在问题的一种极好的解决方案.在website中,每个页面的点击都是用户和系统的交互(输入).假设你有某些需求去维护存储的数据与其显示方式之间的状态,MVC模式就是在你的应用程序非常适合的一种架构
MVC模式在建立方案时专注于三类问题
1.处理持久保存的数据(数据库或文件)
2.处理应用程序的逻辑控制流程,向用户显示什么,在应用程序中允许用户对于数据执行何种动作
3.在应用程序中向用户显示信息
JSP/J2EE在MVC的应用方面比较http://blog.csdn.net/images/blog_csdn_net/fanyamin/102481/r_phpmvc1.gif成熟,有非常多的经验可供我们借鉴,参见以下网址
http://java.sun.com/blueprints/patterns/MVC.html
http://java.sun.com/blueprints/guidelines/designing_enterprise_applications_2e/webtier/web-tier5.html
http://developer.java.sun.com/developer/onlineTraining/JSPIntro/contents.html#JSPIntro4
在JSP规范说明中所提到的"Model 1"和"Model 2"
Model 1: 在系统中用类封装了模型,但是视图散布于不同的布面,也没有页面流程控制器
Model 2: 推荐方式,由控制器对象负责应用程序的流程控制
JSP/J2EE世界中有不少非常精妙的MVC的实现方案,其中鼎鼎大名就有Struts(http://jakarta.apache.org/struts/)
模型Model
Models 是MVC应用程序中实现业务逻辑的组件,而
业务逻辑是与信息存储相关的任何PHP逻辑代码
模型一词来自于真实世界中,它类似于规则与数据
模型是在系统中唯一与持久性数据存贮打交道的组件.
(比如在web请求中保存或检索数据).
模型可在web开发中实现任何技术: 数据库调用,文件处理,会话管理,web services或其他存储数据的手段.
一个设计优良的模型能在web服务器中被其他应用程序使用.
当你开始见识到用这些类封装业务逻辑的威力,你会清楚地认识到制作一个良好的模型是一个非常有用的习惯,即使你不用完全的MVC架构
对于和数据库表交互的模型,一个单独的表最好有一个相关联的一个类
这将帮助我们获得MVC好处的第一点:在某种持久性数据存贮中处理数据
只要坚持MVC的框架,如果数据库表改动了,那我们只需在系统中检查这个对应的模型
在web应用程序中典型的例子就是用户,访问者, 购物车,目录项,订单,标题或文章
在数据库驱动的web应用程序中,模型趋向于关联于单个数据表,或者一些紧密耦合在一起的表(或视图). 作为一种合理的命名规则,模型类的名字可与数据库表的名字类似.
我也倾向于为website的功能写模型类,例如对于多页的表单可以有一个关联的模型向导类.
视图View
视图是MVC应用程序中向用户表示输出的组件.
最通常的PHP应用程序输出是HTML,但视图不仅限于此.
MVC应用程序亦可输出XML, WML, 纯文本,图像, 邮件或其他内容
在视图中PHP有广泛的应用,发送数据到浏览器,实现模板解决方案等
总的来说,视图创建模型的实例,使用模型的方法去获取数据并展现给用户.
在应用程序中,视图包含所有必需的将二进制数据转换为所需的数据表示格式的PHP代码.比如,利用GD库画图的代码在MVC中就属于视图
控制器Controller
控制器是MVC应用程序的核心组件,它必须知道用户的HTTP请求(或者是命令行输入参数),从而决定显示什么视图,或者产生应用程序的其他什么相应动作.
总之,控制器是任何MVC项目的核心组件(主要因为模型和视图必须根据它们的性质而适用于你的应用程序). 不同的项目有不同的策略去决定视图和模型如何交互.
这些对象之间的交互就是系统的耦合.如果用一个配置文件(常用基于XML的文件)来定义它们之间的关系,这就是所谓的"松散耦合". 相反的做法就是在系统中硬编码应用程序流程.
下图描述了Web开发的各种技术在MVC三个组件中的应用
实际情况中,这些技术也许有交叉. 例如如果你的应用程序中包含一个User模型,
而且你有一个"记住我"的功能,你也许想用User模型发送一个cookie值到客户端浏览器. 我们应将这个任务通过HTTP分配给控制器. 还有我们也许要考虑在哪里显示一个模型的实例表示视图,通过URL参数去显示哪一个视图.结果,视图可能通过$_GET来访问获取这些信息.(通过HTTP连接从控制器又到视图). 我们不应该在视图和模型之间看到这些技术的交叉使用.
在模型中决不要夹杂HTML,在视图中决不要包含任何数据库访问功能.
任何以上做法都违反了我们将内容与格式分离的原则,打破了MVC模式,并限制了应用程序的灵活性.
网上已有许多基于PHP的开源项目
Ambivalence
http://amb.sourceforge.net/
This project is a port of the java project called
Maverick (http://mav.sourceforge.net/), which originated
as an attempt to simplify Struts.
Eocene
http://eocene.net/
An MVC framework with a goal to port to ASP.NET.
php.MVC
http://www.phpmvc.net/
A port of the java-based Jakarta Struts framework
phpPatterns() MVC2
http://www.phppatterns.com/index.php/article/articleview/19/1/1/
The second article on this site about the MVC pattern.
Phrame
http://phrame.itsd.ttu.edu/
Another port of the Struts framework.
结合项目实践
一般来说,基于PHP的MVC应用程序都有两个总的流程路径.见下图
第一个流程路径是用户发送请求以获得一个特定的视图.
第二个流程路径是用户输入内容并更新模型的数据
第一个流程路径
1. 控制器负责解释用户以HTTP的GET方式发送的请求.
并针对这个请求,决定切换到哪一个相应的视图.
2.应用程序流程转到视图,通常视图需要来自于模型的数据来显示响应结果.
3.视图请求获取来自于模型的数据.
模型是唯一可以访问持久性数据存贮容器(数据库或文件)的组件.
4.模型向持久性数据存贮容器中查询数据
5.模型从持久性数据存贮容器中获取数据
6.模型向视图返回数据
如果视图需要当前或其他模型中的数据,根据需要重复第三步到第六步
7.视图格式化并发送这些输出给用户作为响应.
![](http://blog.csdn.net/images/blog_csdn_net/fanyamin/102481/r_phpmvc_flow1.gif)
第二个流程路径
MVC Web应用程序另一个的通用流程是在应用程序中由用户更新数据
下图描述这个流程路径
1. 控制器接收到请求(类似于从用户的浏览器以HTTP POST方式提交请求)
2. 控制器决定采取什么动作,并以适当的参数调用模型对象的方法响应这个请求
模型将根据代码中的业务逻辑判断这个请求是否有效
3. 如果请求有效,模型将调用相应的方法改变数据
4. 返回更新结果
5. 模型将控制权交还给控制器
6. 控制器确定用户下一步的指向
7. 重定向到相应的地址,在发布header()命令之后,本次请求就此结束了