首页 > 代码库 > 【原创翻译】认识MVC设计模式:web应用开放的基础(框架约定篇)

【原创翻译】认识MVC设计模式:web应用开放的基础(框架约定篇)

 

翻译:shadowmydx 转帖请注明

在上一篇文章中,我介绍了在框架设计和其他情况中得到广泛应用的MVC设计模式,其中介绍了模型、视图还有控制器:它们不同的职责以及它们之间是如何联系起来的。上述知识虽然是MVC设计模式的基础,但是我个人认为在代码上重新认识这些知识将会是一个完全不同的主题。我想在该系列最后的部分集中精力解决这个主题,但首先我想讨论下web开发框架使用的一些约定以及不同框架之间的区别是如何产生的。


在这篇文章里,我将继续使用雇员-部门应用这个例子来展示Yii框架、Zend框架和Ruby on Rails(这三种框架是我最熟悉的。)如果你使用不同的框架,虽然在细节上会有一些变化,但主要的原理是不会变的,这些不变的原理也是我想在本文中着重强调的部分。在我的下一篇文章中,我将提供一些典型的代码(虽然我想在这篇文章中就解决这个问题,但是这样的话题目就太大了,又会犯自己常犯的老错误。)


每一个MVC的组成部分都需要一个单独的分离文件,甚至多个文件,比如视图部分。在雇员-部门应用中,需要雇员部分的各类MVC组件以及部门部分的各类MVC组件。换言之,模型文件夹中包含了雇员模型文件以及部门模型文件;控制器文件夹中包含了雇员控制器文件以及部门控制器文件;视图以此类推,但有些许不同之处,就是对于雇员和部门而言不只有一个视图文件,而可能是多个。对于Yii框架而言,模型文件往往被命名为ModelName.php,例如Employee.php。作为一个命名约定,Yii使用开头大写的单数单词来命名;Zend中,将会是Employees.php,是复数形式;在Ruby on Rails中,将会是employee.rb,单数但开头是小写字母。在这些文件中将定义一个模型类,类的名字将匹配文件名字,在Yii中类名就是Employee,在Zend中就是Employees,在Ruby on Rails中就是Employee(注意Ruby使用小写字母作为文件名但在类名上第一个字母仍然大写,就如同大多数其他语言那样。)

 

 

在一个模型类的内部,属性和方法用来定义这个类的各种行为。根据不同的框架,可能表现的行为有:指明与其他模型的关系,提供认证规则,将模型的数据转化为需要的格式等等。


如果模型基于一个数据库中的表,这个表也将拥有一个与其匹配的名字,例如Yii中的Employee,Zend中的employees,Rails中的employees。根据不同的框架,表中的主键或者是id,或者是tablenameId,或者是tablename_id。关于这些约定,需要注意的地方有两个:首先,大多数的框架允许你修改标准的行为,例如改变表名和类名之间的映射关系。其次,最好遵守那些框架制定的约定。就个人而言,我喜欢使用小写字母和复数形式来命名我的数据库表,但如果我在使用Yii的话,我也会使用头字母大写的单数表名来保持与Yii约定的统一(当然,尽管大多数情况下数据库软件并没有大小写之分)。你当然可以多写些代码来调整模型中的非默认行为,但是比起遵守约定而言,那不过是些多余的工作,并且很容易引起BUG。

 

对于大多数模型而言,你也同时会拥有与之相对应的控制器(并不必然,比如:你可以有一个不和模型关联的控制器,或者有一个没有与之相对应控制器的模型)。对于这三种我用得最多的框架,控制器往往保存在controllers文件夹中,同时以控制器的名字来命名文件名:Yii中的EmployeeController.php,Zend中的EmployeeController.php,以及Rails中的employees_controller.rb。在这些文件中,定义了这些控制器类:Yii中的EmployeeController,Zend中的EmployeeController,以及Rails中的employeesController(类名都采用驼峰命名法)。

 

在控制类内部,不同的方法确定了不同的行为。对于雇员而言,共同的行为包括:create(或者new),update,delete,list(all),以及show(one)。在Rails的Controller类中,你的方法可以如此命名:create,update,delete,show,list。Zend和Yii需要在各个方法名字前面加一个单词action,Yii中的情况:actionCreate,actionUpdate,等等。Zend中的情况:createAction,updateAction等等。这些方法定义了特定行为的具体步奏。

 

(在这里先提一下,我将会讨论URL如何绑定特定的行为。大多数web开发框架都会管理URL来使得他们更加清晰易读和对用户友好。框架首先会运行一个“引导程序” —— 例如index.php或者index.html之类 —— 来处理用户的请求并适当的重定位用户到相应的页面。比起www.example.com/index.php?controller=employee&action=list这种丑陋的地址来,用户会看到类似www.example.com/index.php/employee/list这样的地址。这个地址简单的表明了用户需要的控制器和控制器需要执行的动作。怎么样,是不是好多了?)

 

最后让我们来看看位于表现层的视图吧。同样的,视图文件保存在views目录下。大部分框架会把视图目录下的视图文件继续组织成不同的子目录:一个储存雇员视图的文件夹,以及另一个储存部门视图的文件夹。在Yii和Zend中,这些文件夹名字是单数,而在Rails中,他们将是复数。不同的视图文件将对应不同的行为,在Yii中,这些视图文件会被命名为create.php,list.php,show.php,以及update.php,plus_form.php(创建和改变数据所使用的同一部分)。在Zend中,这些文件被命名为edit.phtml,index.phtml等等。在Ruby on Rails中,将会是edit.html.erb,index.html.erb,new.html.erb以及show.html.erb。

 

当然,还有一个重要的视图文件:布局文件。这个文件(或者这些文件,有一些网站会有一些不同的布局文件)建立了一个整体的模板:<html>标签、被包含的css文件、网站headers,导航条,网站页脚以及</html>标签。其他的视图文件将会嵌套在这个布局文件中来产生具有不同内容的页面。这种方式把网页不变的部分抽离了出来,比如网站导航条,然后在各个不同页面之间实现了代码的复用。在Zend中,布局文件是layouts/scripts/layout.phtml(注意,layouts目录与views目录共享同一个父目录,是平级的,而不是位于views目录中);Yii中,布局文件是views/layouts/main.php;Rails的话,会为每个模型产生一个默认布局:views/layouts/departments.html.erb以及employees.html.erb。你将会学到,你可以通过在控制器增加一些代码来改变布局。例如,我创建了一个项目,主页使用的布局和其他页面不一样,那么我可以重写SideController类中的indexAction方法来改变我想使用的布局(index动作是控制器的默认动作,同时siteController是整个应用的默认控制器)。

 

嗯哼,关于目录结构,文件名,以及类名/方法名约定的介绍就暂时告一段落。这部分知识我们似乎讲得太多了,但是,在讲解具体的代码和主题以前,我认为弄清楚代码究竟在何处运行起来是十分重要的。我其实也在考虑是否应该在这里提供些目录结构的实际截图,但那里还有些我没有讨论过的文件夹和文件,我担心这些会分散了这篇文章的主题。在下一篇关于MVC的文章中,我会拿出真正的代码来说明MVC模式的各个成分。

修改:这是根据观众要求增加的目录结构图片

 

Yii的默认目录结构中,所有的东西都位于你的web根目录下(Apache的情况:htdocs)。你的应用保存在protected文件夹中。在这篇文章中,我主要讲了controllers文件夹、models文件夹以及views文件夹。yiic、yiic.bat以及yiic.php脚本是用来生成web应用的。根目录下面同样包括css文件、js文件以及需要的各种媒体文件。index.php就是我们的“引导程序”。

 

【原创翻译】认识MVC设计模式:web应用开放的基础(框架约定篇)