作者:feifengxlq
原文地址:http://www.phpobject.net/blog/read.php/95.htm
时间:2007-1-10    
  很早前就想写一些关于PHP实现MVC的新的体会。今天就开始详细的写写我对MVC的一些理解,以及我在开发过程中实现自己的一个框架的一个流程。其中或许说的不正确,还望指正!

   以下是关于这个MVC的文件结构图:
点击在新窗口中浏览此图片

    网站关于MVC的教材很多了,我这里不具体说了,不明白的,推荐自己上百度搜索下“MVC",相信可以找到你想要的东西的。这里我谈谈在PHP实际开发中,我对MVC的理解。M,module,主要任务是把数据库或者其他文件系统的数据按照我们需要的方式读取出来。V,view,我的理解是主要负责页面的先是,把数据以html的形式显示给用户。C,controller,主要负责业务逻辑,比如说你要显示登陆界面,就需要调用一个控制器userController的方法loginAction来显示(可能这个不需要调用module),再比如你进行登陆检查就可以调用userController的方法checkAction来进行逻辑处理。(感觉Verdana的指正^_^)。
引用

M是指model。Controller 并不参与业务逻辑,整个业务逻辑部分应该是放在 Model 层中的。Controller 只起到分发请求的作用,也就是说得到当前的 Request,决定调用哪个 Model 获取数据,然后再赋值给哪个 View 来渲染页面


   具体实现MVC,我觉得最好还是要做到单点入口。
   什么是单点入口呢?所谓单点入口就是整个应用程序只有一个入口,所有的实现都通过这个入口来转发,比如说在上面我们就使用index.php作为程序的单点入口,当然这个是可以由你自己任意控制的。
   为什么要做到单点入口呢?单点入口有几大好处:第一、一些系统全局处理的变量,类,方法都可以在这里进行处理。比如说你要对数据进行初步的过滤,你要模拟session处理,你要定义一些全局变量,甚至你要注册一些对象或者变量到注册器里面(主要是实现在全局,具体你可以参考我先前翻译的一些文章《在PHP中使用全局变量》)。第二、程序的架构更加清晰明了。当然好处还有很多的,我也不一一列举了,具体你可以去体会。
   当然单点入口也存在一些不足,比如你系统大了后,不可能只一个点做为入口,尤其系统存在两个完全不相关的功能时候,不过很高兴的说,这个是可以扩展,你可以扩展多个入口。比如说在最近一个大项目中,后台的管理和前台是不相关的,所以我就会有两个入口,一个是index.php一个是admin.php。但这不不是说单点入口不好(具体含义你可以揣摩下)。
   那么,如何实现单点入口呢?这是我本节的重点。一般来说都是通过url的地址映射实现的(前面我有一篇文章说到这个:《回答PHPCHINA上的几个问题:URL映射》,里面实现了单点入口的核心,这里我具体实现,并演示下)。单点入口最关键的就是通过url传递参数来实现程序的分配,具体说,比如:地址是index.php?controller=test&action=test,这就通过index.php把请求转发到对应的testController文件中,并执行其对应的testAction方法(这里的控制器和方法的命名都参考了Zend Framework的思想)。
   下面我们用最简单的方法是来实现上面说的单点入口(记住:简单起见,我这里没有使用URL映射了)
    /index.php

<?
/**
  * MVC演示demo
  * 仅仅实现最基本的MVC功能,不包含安全处理,数据过滤,及其他优化措施。
  * @author:feifengxlq
  * @since:2007-1-10
  * @copyright http://www.phpobject.net/blog/read.php/95.htm
*/
define('SITE_PATH',str_replace('','/',dirname(__FILE__)));//定义系统目录

$controller=(!empty($_GET['controller']))?$_GET['controller']:'index';//获取控制器,默认index
$action=(!empty($_GET['action']))?$_GET['action']:'index';//方法名称,默认index

$controller_name=$controller.'Controller';
$controller_file=SITE_PATH.'/app/controller/'.$controller_name.'.class.php';//获取控制器文件
if(file_exists($controller_file)){
    require_once(
$controller_file);
    
$controller=new $controller_name();
    
$controller->{$action.'Action'}();
}else{
    die(
'找不到对应的控制器!');
}
?>


对应的一个演示demo
/app/controller/testController.class.php(注意路径)

<?
/**
  * MVC演示demo
  * 仅仅实现最基本的MVC功能,不包含安全处理,数据过滤,及其他优化措施。
  * @author:feifengxlq
  * @since:2007-1-10
  * @copyright http://www.phpobject.net/blog/read.php/95.htm
*/
class testController
{
    function 
testAction(){
        echo 
'Hello,World!';
    }
}
?>


打开浏览器,输入http://path/to/yoursite/index.php?controller=test&action=test(注意相应的修改你的路径),如果你看到Hello,World!说明MVC第一步,单点入口成功了!

   提供演示demo下载:
下载地址:http://www.yanxue8.com/?file_568
评论(10) | 引用(820) | 阅读(12943)
jingangel Says: Homepage
2008/07/23 13:45
还是不太懂啊
xueer Says:
2008/05/01 17:01
提供演示demo下载的那个附件无法下载呀希望可以发给我!谢谢!我的邮箱是zhangxm335@126.com
pipi Says:
2007/05/30 10:42
我很想要这个demo,但是我无法下载,能不能发到我的邮箱里
我的邮箱是wuchuan_chuan@yahoo.com.cn.谢谢了
可以下载了。
feifengxlq 回复于 2007/06/01 21:54
ice Says:
2007/03/11 03:46
补充:又看了一下Symfony的文档,发现还是把action归入controller layer的……收回上面说Symfony修正了错误的那句话。
再PS. 这个blog对评论的分页导航不对啊,从分页的数量上来看,似乎是把引用的数量当作评论的数量来生成分页导航了?
ice Says:
2007/03/11 03:36
Verdana说得是对的,C不应当有业务相关的内容,那是M的工作。我认为问题的核心在于action的定位,或者说,M的定位。单纯把M定义为数据库(或任何其他的数据源)数据的包装/映射是不对的,M应当是数据库数据,加上所有业务逻辑之后形成的混合体。从具体的实现上来考虑,我认为应当划分为两个层面:首先对数据库进行一个包装(某些简单的业务逻辑操作也有可能被包装入这一层面),这一层次的包装事实上对应于很多框架内所谓的M(比如FleaPHP);而第二个层面就是对各种可能的业务逻辑的封装,这一层面封装应当以操作,或者说命令为单位,每一个操作(命令)对应一段具体的业务逻辑操作。很容易看出,这恰恰对应于action。因此action应当归入model的范围而非controller。出现争论的原因在于错误的把部分model的内容(action)划分给了controller。
犯这个概念上的错误的framework绝非少数,比如说zend framework就是(class zend_controller_action,官方文档内也有“Zend_Controller_Action is the base controller component.”的言语),fleaPHP我没有深入用过,但是从粗浅的了解上来看似乎也是一样的问题。symfony v0.6版对应的文档(就是那个somfony book)上也写道“In symfony, the Controller is separated in different parts, namely a front controller and a set of actions.”,可见也是同样的问题。不过现在(v1.0.0)改用那本已经出版的《The Definitive Guide to symfony》作为官方文档,在里面翻了翻似乎已经没有这句话了,不过似乎也没找到明确的说action是M的一部分的说法。不过对symfony来说,这只是个概念上的问题,它使用的是独立的sfAction类,不管概念上归于C还是归于M,实际的程序代码不受影响。
也有framework正确的把action归入了M,比如php.MVC(http://www.phpmvc.net/),看首页的Introduction就写的很明白。symfony在1.0版本中应该可以算是把这个错误改过来了吧。java阵营的Struts似乎提供的也是action抽象类,不过没有深入研究过代码和文档,说错了莫怪。
事实上,这个问题的修正非常、相当、极其的容易。因为主要的是概念上的修正,实际的框架与程序代码修改非常少,一般来说顶多就是要修改action对应类的类名罢了……如symfony的情况甚至根本什么都不用改。

PS.google以下可以找到下面这个关于MVC的文章,个人认为此文已经对MVC给出了相当好的描述(只看第一部分就可以了)。
http://www.itisedu.com/phrase/200604231324325.html
ssbs2004 Says:
2007/02/18 15:36
为什么附件下载不了呢?能不能发一份给我谢谢了ssbs2004@163.comsmile
tee Says: Email
2007/02/08 20:30
hi,飞风,
我没办法下载《PHP实现MVC开发得最简单的方法——单点入口 》和《PHP实现MVC开发得最简单的方法——视图及模版技术 》这两个附件。能不能发到我的信箱。
谢谢。
Finian Says:
2007/01/11 23:55
嗯,我也发现Verdana所说的问题。比如FleaPHP框架的示例程序中,Model只仅仅负责存取数据这一块(对数据库操作进行封装),而Controller却承担了很大一部分的领域逻辑。如果按照严格的MVC模式来说,领域逻辑应该放在Model而不是Controller。
我觉得在WEB开发中,业务逻辑放到controller里面可能更好。比如说你一个业务涉及到对多个表的处理。如果你直接在model里面处理,其实对model压力很多,而且感觉程序的可读性不好。
所以,我觉得有时候不一定要完全按照MVC的框架一成不变。
feifengxlq 回复于 2007/01/12 00:27
rover Says:
2007/01/11 09:36
mvc我推荐CodeIgniter框架

demo不能下载
呵呵,可以下载。你再试试。

CodeIgniter我以前没看过,刚刚搜索下。好像它是实现了很多功能,不仅仅是一个MVC模式,它还有一些文件上传之类的库类。

另外感觉过于复杂。

我这里希望是用最简单的方式来说明如何实现MVC。希望对理解MVC起到抛砖引玉的效果
feifengxlq 回复于 2007/01/12 00:14
Verdana Says:
2007/01/11 09:08
M 是指 Model,不是 Module
另外个人觉得博主对 Controller 的理解还是有偏差,Controller 并不参与业务逻辑,整个业务逻辑部分应该是放在 Model 层中的。
Controller 只起到分发请求的作用,也就是说得到当前的 Request,决定调用哪个 Model 获取数据,然后再赋值给哪个 View 来渲染页面,说白了就是黏合 Model and View.
嗯,感谢楼主的指正。M是model。

对,MVC中的控制器一般是只负责接受请求,并决定由那个模型(Model)去处理请求,然后用试图去渲染页面(View)。但在PHP开发中,很多时候我是直接控制器(controller)是集成了model的部分功能的。我认为Model只要负责把需要的数据按格式取出来,然后由controller进行相应的流程逻辑。
feifengxlq 回复于 2007/01/11 09:20
分页: 1/83 第一页 1 2 3 4 5 6 7 8 9 10 下页 最后页
发表评论
昵称 [注册]
密码 游客无需密码
网址
电邮
打开HTML 打开UBB 打开表情 隐藏 记住我