在公司项目中实验了一把PHP下的MVC,在我看了不多的几个MVC框架,我个人对其封装不算满意,zend的没看过看过介绍,但其层次和组织结构过于复杂而且其重点也是在于通过zend框架使得功能更方便。倒是国内的两大主力fleaphp和thinkphp,flea我曾经简单用过,感觉各方面都还不错,重量也把握不错,thinkphp对内核的东西改变较多,而且有些思路也相当不错。think的代码我基本上都读了(0.92)现在好像有1.0了,没有再仔细读,但基本思路已经了解了。于是非常冲动,也想实验一把,曾经也为了体验一把MVC设计,基于spring的mvc框架做了较大规模的封装(不过事后发现是我对spring了解不够足,其实我做的封装spring也基本都做了,包括所谓的command概念我居然也实现了一个类似的玩意)。这次手痒于是我们就开始吧。但在实践中遇到了相当大的阻力,首先是进度根本无法保证,导致最后被罚了1k工资,但我并不太在乎这点,因为从这里边积累大量宝贵经验,当然也让我对PHP彻底失去了兴趣,不过这是后话,首先来看看我的MVC概念。

个人的MVC思路均来自于《J2EE设计模式(J2EE Design Patterns)》一书,最基础的框架:


这是一个标准的单分法器模型,但我会作几点说明:
1 RequestObjected,这个是所有用PHP的程序员可能不理解的地方,事实上PHP是一种为网站所生的语言,JAVA这方面没有任何的天生优势,JSP更感觉是一个可笑的玩具,现在大多数做企业应用还在用传统的JSP技术是会被BS的,BS的地方我在这里不做讨论了。回来吧,首先我们知道PHP对于Request有非常理想的封装了,包括如下的全局对象,$_GET $_POST $_COOKIES $_REQUEST $_SESSION 但请大家注意,这些对象都是全局变量,对于封装来说这是完全违反对象法则的,所以我对$_GET 等等做了封装在我的类里边会在BaseAction中有一个叫ParamData用作request对象 cookieData对应cookies sessionData对应session,为什么这么做,对于一般人的理解这样等于增加了消耗,那你就错了,我绝不单单为了对象而作生搬硬套,这样做的好处有如下:
1) 完成request层的编码转换,比如开发UTF-8的前台是,目前所有的框架都使用了,不同的文件编码模式,这个方法在我看来非常愚蠢,可以看到fleaphp就有utf-8和gbk两种编码的源码,这种方法对于开发来说不是什么好事情,而我在这里做了封装就可以在基类做自动化转换,已知我的程序都是gbk编码,那么你用什么编码在配置文件中有,可以实现对request的自动编码转换,再也没有编码困扰了。
2) 使得这些只读对象成为了可读写的对象,很多人会问这是干什么?当然有用!因为你别忘记了过滤器,这些过滤器本身也是一个缩小版的action如果得不到它的“爸爸”怎么干活?但这些过滤器都是没有返回的(我设计成没有返回的,因为PHP的对象太差)但这样就有问题了,我做了一个操作怎么告诉爸爸呢?比如我做一个验证工作,过滤了某些request的危险字符,怎么告诉爸爸?好了我的paramData对象就是干这个的,如果你用$_GET $POST,那么你只能哭爹喊娘了!
2 模板,这边模板写得非常粗略,这也是我的一个亮点,当然我得承认这个思路来自于目前公认的最好的MVC实践ROR的思路,顺便说下我整个框架的配置非常少,这些都是ROR的约定代替配置的思路,对于JAVA习惯用SPRING的同志,我想写个几百k的配置文件很正常,更有甚者以配置长度论水平,这也是一个笑谈啦,但至少在PHP不用这样,原因就是PHP是脚本,本身PHP的任何程序都是脚本,只要你需要,完全可以这么搞。好了,说了一段废话,回到模板,ROR的思路是什么?我现在这样实现的

模板path= BasePath+actionName/MethodName.DocmentType
所以你会看到我的模板目录下文件爆多,这是一般人应用所没有的,但我至少认为这里有两个好处:
1 可以对应找到所有的文件
2 可以有效的灵活配置,和ROR的思路有点不同,我至少可以通过Action改变当前模板(ROR也可以啦,不要误解了),但后面会在Action部分说到一个创新的地方就是内存模板概念(首先说明这对于很多人是蛮新颖的,但在我们公司这已经一直这样用了,我只是拿过来改个名字封装下而已),所以这里必须要有个灵活的方法。
下面看一个典型的Action吧:
<?php
require_once(RAILS_PHP_LIB.'/class.Action.php');
class tag extends Action {

//主页方法
function index(){
$user = $this->userClass->getUserInfo($this->paramData['userid']);
$articles = m("articles.getArticleList",array("page"=>1,"user_id"=>$this->paramData['userid'],"size"=>50));
$this->addTemplateData("user",$user);
$this->addTemplateData("articles",$articles);
}


}
?>

至于代码的含义以后会介绍的,这里大家只是看看,模板的用法,大家会问模板呢?当然是在基类中实现的,至于基类怎么实现就是各自的事情,我个人觉得如果有兴趣可以重写或者继承覆盖,因为只要实现几个方法就好了。

好了,今天讲到这里,我要干活去了,忘记介绍这个东西的名字了叫:RAILS PHP,目的很清楚了,其中有不少ROR的思路,当然我对ROR的理解并不深用得也不算多,只做过两个小东西,不过我个人很喜欢ROR的思路,呵呵,今天作为引子就写到这里,下面看看我接下来会写什么:

为验证准备——UserClass接口
最核心的类——Action
Action的儿子MemoryAction
Action的流程控制,唯一没有真正对象化的地方
Action的过滤器
神奇的模板,原来Smarty可以这样玩——RTemplate
数据库层,失败的作品,但我想说说我的规划思路
分法器,异乎寻常的简单
Cache我心中的痛,PHP你为什么没有真正的Static
应用的扩展文档模型——给做CMS和BLOG等文档系统一点小思路
最后的结尾,未来的发展之路

最后说几句,对于PHP我是菜鸟,真正用PHP不过8个月的光景,只是我觉得语言是相同的其实都一样PHP虽然差,但也应该是对象语言至少可以做到,虽然这点在公司的老程序员面前得不到一点肯定,但我只想证明我的思路没问题,欢迎有人来拍砖,共同讨论才能帮助我进步,虽然个人已经非常bs php了,但是要靠它吃饭拿工资没办法,但是yy下总可以吧,那就y啦。

还要抱怨的是开发工具,我的同事们都是用editplus的我实在无法接受那样的IDE,用了zend,不过即便如此有几个问题无法解决:
1 类中应用了另外一个类,那么那个类就无法代码提示
2 对于类型无法事先确定,而我的多数函数参数都受到设计模式的影响,均是传对象的,这样就开发和调试带来了很多莫名其妙的问题,常常被参数缺失而困扰
但这些问题不能抱怨zend不能抱怨eclipse,因为PHP就是没有类型的即使所谓的class在我看来只是一个名字声明而已,这非常糟糕,看看netbeans的ruby ide如果能达到这个水平基本上无憾了可以,但现实却那么打击人,抱怨一下。
Tags: ,
PHP日记 | 评论(0) | 引用(0) | 阅读(602)
发表评论
表情
emotemotemotemotemot
打开HTML
打开UBB
打开表情
隐藏
记住我
昵称   密码   游客无需密码
网址   电邮   [注册]