虽然MVC对于现在的web开发人员来说都已经很了解,但如何适当的在现实工程中使用,还是困扰着许多童鞋们。MVC的中心思想就是“代码重用与关系分离”。以下,我们描述一些在使用yii框架开发时,更好的遵从MVC原则的常用方法。
为了更好的解释这些方法,我们假设这个web工程包含以下一些子工程:
●前端:一个面向终端用户的网站
●后台:一般提供给后台管理员使用,用来管理网站的。
●控制台:运行一些控制指令,系统的定时任务等。
●Web API:为接入的第三方提供接口。
这些子工程可能由一些模块组成,也可以作为yii的工程与其他yii的子工程共享代码。
模型
模型代表了一个Web应用程序的底层数据结构。模型在一个web工程中,经常会在不同的子工程间共享。例如,LoginForm这个登录模型,作为前端与后台都可以使用;一个公告模型,会被前端,后台,控制台,WEBAPI都使用。所以,模型必须符合以下特点:
1、允许包含属性,用来代表特殊数据。
2、允许包含业务逻辑,来保证这些数据满足设计的要求。
3、可能包含一些代码来操纵数据。例如,在搜索中,包含了一个search的方法来搜索数据。
有时候,遵循上述的第三条,可能会导致一个模型非常的庞大,导致在一个类当中,包含了太多的代码。如果在代码中包含了太多不同的功能,这也可能导致这个模型难以维护。例如,一个公告模块,可能包含了一个叫做getLastestNews的方法,这个方法只有前台的子工程调用;而这个公告模块,同时也包含了一个叫做getDeletedNews的方法,这个方法只有被后台工程调用。对于一个中小型的工程,这样可能还影响不大,对于大型工程来说,以下几个步骤有利于这个模型的维护工作:
1、定义一个NewsBase的基类,这个类里面只包含了一些子工程都会调用到的功能;
2、在每个子工程中,定义一个News的子类,继承于NewsBase。每个子工程在自己的这个类里面,定义一些专属的方法,例如前端的实现getLastestNews,后台的实现getDeltedNews。
一般来说,模型不允许包含直接处理终端用户的逻辑。更甚的是:
●不允许使用 $_GET, $_POST, 或者其他类似的终端用户绑定的变量。必须牢记的一点,模型是可能被用于完全不同的子工程(例如单元测试,webAPI),这些工程或许不是通过这些变量作为用户请求。这些终端用户变量,必须有控制器(Controlloer)来处理的。
●不允许包含例如HTML等的呈现代码。因为这些表象代码可能根据不同的终端用户而不同的呈现。例如上例中的公告模块,前端用户跟后台用户,可能是不同的表现。所以这些工作最好还是由视图(View)来做。
视图
视图用来表现模型中的数据,他把模型中的数据按照终端用户所想要的形式给表现出来。一般来说:
1、允许包含一些表现的语句,例如HTML,以及一些简单的PHP语句,用来处理遍历数据,格式化数据,渲染数据等。
2、必须避免一些数据库操作的语句,这些语句最好是放在模型当中。
3、避免直接操作$_GET, $_POST或者是类似的终端用户有关的变量。这个是控制器的工作。视图只要做好控制器或者是模型传送给他的数据输出,但不要涉及到请求变量或者是数据库操作。
4、允许访问控制器或者是模型的方法或属性,但这个只是为了用来表现数据而已。
视图可以有多种的重用方法:
1、布局(layout):通用的区域可以放在布局的视图中,例如页头,页脚。
2、局部视图(partial views):用局部视图(没被布局渲染过的)来重用表现的代码段。例如,我们用_form.php 这个局部视图来渲染新增或者是更新模型的输入页面。
3、小工具集(Widgets):如果需要用很多的逻辑代码来表现局部视图的话,这个局部视图最后是做出小工具,这个小工具的类文件是实现这些逻辑代码的最好地方了。对这个widgets来说,如果需要生成很多的html标签,这些标签最后是放在view文件。
4、帮助类(Helper Classes):在视图中,我们经常需要一些代码段来实现一些小的功能,例如数据格式化,生成html标签等。比起把这些代码段直接放在视图文件中,一个更好的解决方法是:把所有这些代码段放置于“视图帮手类”。然后,只要在你的视图文件中,调用该帮手就可以了。Yii提供了一个这样的样例,强大的CHtml 帮手类。他可以用来生成常规的html代码。帮手类必须放置于自动加载目录,“autoloadable directory”。这样不需要声明就可以引用了。
控制器
控制器是把模型、视图以及其他组件关联起来工作的主干。控制器是对终端用户负责的,所以:
●可以访问$_GET, $_POST 以及其他的终端用户PHP变量。
●可以创建模型实例,并管理他的生命周期。例如,在一个典型的模型更新动作,控制器会先创建一个模型实例,然后将用户通过输入窗口post过来的数据,更新模型。在保存更新后的模型成功后,控制器可能重定向终端用户到这个模型的信息页面。注意的一点,保存新模型必须是在模型里面实现完成,而不是在控制器中。
●不允许包含SQL语句,这些应该在,模型中处理。
●不允许包含任何表现语句,例如HTML等。这些必须在视图中处理。
在一个良好的MVC架构工程中,控制器通常来说都是很小很简洁的,可能只有几十行代码;而模型中,则是很肥胖,用来做数据处理。这是因为,对于特定工程来说,数据结构以及业务逻辑都需要经过特殊的处理,都需要通过定制来实现客户要去。控制器的逻辑一般只是简单的底层框架或基类调用。