本文原来是为了回答一个网友的问题 (何为MVC?应用smarty后,也只有mv,那里来的C呢?)http://www.phpchina.com/bbs/viewthread.php?tid=51395&extra=&page=1
现把它整理成一篇文章,方便阅读。
====================================================
问题 :何为MVC?应用smarty后,也只有mv,那里来的C呢?
------------------------------------------------
goodonyou:
MVC是一种OO开发模式,比较多的用在GUI (Graphic User Interface)系统里。因为PHP面向web编程,采用MVC模式是很自然的了。在MVC模式里,用户界面可以看成是V (view),也就是浏览器里呈现出来的东西。C (controller) 可以是界面里的按钮,输入栏,等等;也可以是程序里预定的控制程序。 M (model) 就是响应每一个C 的应用程序。比如,用户进入一个登陆页面 V,V 里面有一个表单,两个输入栏,要求用户输入用户名,密码,然后按登陆按钮,登陆按钮就是一个C,C再调用M,M的作用就是把用户输入的数据与数据库里提取的数据作比较,如果正确,就把正确的信息传给V,如果不正确,就把不正确的信息传给V。
不用smarty也可以用MVC模式,用了smarty后,就是在V里面把PHP代码与HTML代码分开而已。假如用了smarty后只有MV,没有C,是因为你没有用MVC模式来开发,没有建立C控制层的概念。
MVC模式是OO编程中的一种设计模式,一种贯彻方法,一种思路。核心思想是将表现逻辑层和应用逻辑层分开,并利用控制层来进行控制调度,以达到将复杂问题简单化的效果。没有框架也可以用MVC模式编程。
MVC要它的优势,也有其局限的地方。希望大家对其有了比较深入的了解后,能扬长避断的使用。
-------------------------------------------------------------------------
M同学:
我是这样理解的:
M是一个或多个类,每个类里封装了对一个或多个数据表进行增、删、查、改的若干个方法。C用来接收客户端发来的get、post信息,然后调用M里相应的方法,进行数据库的存取等操作,然后将响应结果传递给V来输出html
------------------------------------------------------------------------
goodonyou:
这样理解没错。因为书本上就是这么讲的。但是我也向你提个问题:根据你的理解,能说说怎么用MVC方法来贯彻一个页面呢?比如我说的那个登陆页面?:-)
-------------------------------------------------------------------------
M同学:
1. 显示“输入用户名和密码”的html页面:
C判断没有post任何数据进来,则调用V来显示“输入用户名和密码”页面
2. 接收了用户输入的用户名和密码:
C判断post进来了用户名和密码,然后C调用M查询用户名和密码是否匹配,如果匹配,C调用V显示“登录成功”等信息,如果不匹配,C调用V显示“用户名或密码错误”等信息
在这里M用来进行对用户表(记录用户名和密码等信息的表)的增删查改等操作,V用来生成html,C用来根据get、post来控制程序的运行流程
--------------------------------------------------------------------------
goodonyou:
M同学说的不错,谢谢你。但感觉有点像是从过程编程的角度来分析的,而不像是从OO的角度来分析的,是否如此,M同学能否给大家解释一下吗?比如说你打算怎么用函数或类来实现这些要求,假如用类,怎么能尽量做到代码重用?你感觉这种做法(函数或类)有那些好处,那些缺点?
--------------------------------------------------------------------------
M同学:
//m.class.php
class M($db)
{
private $_db;
public function __construct($db)
{
$this -> _db = $db;
}
public function add($param)
{
...
}
public function delete($param)
{
...
}
public function get($param)
{
...
}
public function modify($param)
{
...
}
}
//v.class.php
class V extends Smarty
{
public function __construct()
{
...
}
public function display($tpl, $title = null)
{
$this -> assign('title', $title);
parent::display($tpl);
}
...
}
//v1.class.php
class V1 extends V
{
public function display()
{
parent::display('v1.htm', ‘....’);
}
}
//c.class.php
class C
{
static $m = null;
public function xxx()
{
$v = new V1();
$m = $this -> _getModel();
$v -> assign('var', $m -> get(......));
$v -> display();
}
public function yyy()
{
...
}
public function zzz()
{
...
}
private function _getModel()
{
if (!is_null(self::$m))
{
self::$m = new M();
}
return self::$m;
}
public function __construct()
{
//根据query string判断调用哪个方法(xxx、yyy还是zzz)
}
}
//index.php
require(.......);
require(.......);
require(.......);
...
$c = new C();
我的程序里类似是这样的,M里的方法可以被不同的C重复使用,C因为是根据query string来判断运行哪个方法的,所以做不到重用。没看过别人的代码,不知道他们是怎么写的。
--------------------------------------------------------------------
goodonyou:
你这个MVC的架子做的不错。我想你也是刚学OO不久,能做成这个样子,真要恭喜你了。
不过有几点看法,提出来跟你和大家共同讨论一下。
1。OO代码的重用性和扩展性。
代码能尽可能做到重用与容易扩展,是体现OO语言优势的一大特色。把MVC架构用于web的开发,意味着几乎每个页面都要用到MVC。因此我们在设计类 (class)时就要设法尽可能做到代码重用;又因为每个页面都不同,因此又要想办法做到这个类容易扩展。(如果谁认为在他的项目中无法做到这两点,那就考虑不要用OO了。)
结合你的例子,我认为如果把每个页面里的每个M,V,C里共同需要的内容和参数放在一起,做成一个父类的M,V,C; 到了实施具体页面时,我们再做一个子类的M,V,C,差异的部分在子类里贯彻,这样我们就能较好的贯彻了代码的重用性和扩展性了。
2。MVC架构每部分的功能
这点我们在上面的帖子里已经在理论上讨论过了,到了实际应用时,又可能要根据项目的具体情况,对每部分包含的内容作适当的调整。
对V部分,V主要是用来表述要显示的内容或数据。可能是HTML数据,可能是XML数据,可能是图表数据。。。表现的方法和格式也是多种多样的。V就是用来处理这些问题的。在你的例子里,V只是用来调用一个smarty模板。如果所有项目都是用HTML 和smarty来表现数据的话,我觉得调用模板的功能,放在C里来控制似乎更好一些。 (考虑到以后扩展性的话,也可以把它分开)。 V可以把重点放在如何表现数据上面。
对M部分,在Java里面,M主要是用来处理数据层的,因为Java里数据层包含的内容多且复杂,如RDMS,mail server, directory service. message queue 等等,业务层一般就用Javabean来做了。在PHP里没那么复杂,就把它们都包括了。但是一般都分为数据处理和业务处理两部分。业务复杂的,业务处理部分再细分,如产品类,订单类,等等。在你的例子里,这个M似乎只处理数据层,不处理任何业务逻辑。因为在这个简单的例子里,业务逻辑简单(只有 get_data() 和 compare()两部分),所以放在C里也可以,但这种设计,在以后碰到复杂的业务逻辑时,C就会不负重荷了。
对C部分,主要用于页面流程的控制调度。本身不处理业务逻辑。所以,在你的例子里,似乎没有必要设计三个函数(xxx, yyy,zzz),这是属于M的东西。
C可能的实现方法之一:
class login_controller extends Controller
{
private $input;
public $result;
public $output;
function check_input($input){ //这部分也可以独立出来, 设一个类。
$this->input = new check_input($input);
}
function dispactch(){ //根据需要调用不同的model
switch($this->input){ //在类里面,一般尽可能不要用这种条件语句,可使用继承方法产生子类,这里我偷懒一下。
case a:
$this->result = new login_model_a($this->input);
case b:
$this->result = new login_model_b($this->input);
。。。
}
}
function display(){
$this->output= new login_view($this->result, DISPLAY_TYPE);
}
}
用MVC的好处:
* 各施其职,互不干涉 --在MVC模式中,三个层各施其职,所以如果一旦哪一层的需求发生了变化,就只需要更改相应的层中的代码而不会影响到其它层中的代码。
* 有利于开发中的分工 -- 不用多解释了。
* 有利于组件的重用 -- 不用多解释了。
* 有利于项目的反覆修改 -- 改变或增加功能时,加一些class就行了,不用在原代码上翻来复去的改。
缺点:
* 学习曲线长
* 设计难度大 -- 设计的不好,会导致代码的重用性和扩展性差,还不如用面向过程编程,我想这也是很多人抱怨OO编程的原因之一吧。
* 模型和视图的分离使调试比较困难,但容易发现错误
* 代码文件增多,项目开始阶段,化的时间肯定比过程编程多
综合上述,如果能把握的好,MVC模式会使得你的应用更加强壮,更加有弹性,更加个性化。
限于本人的水平有限,说的不对的地方,请大家批评。