首先说说废话(不想看废话直接跳到第 5 段):这次做着项目,开始的时候队友说这简单的系统用什么框架啊!于是也就放着zend没用,直接开始写几乎没设计的代码!项目前期进展速度极慢,一是因为队里没有一个人对PHP很熟。最开始阶段配置PHP运行调试环境就搞了两天(可能也是大家有些拖吧)。两天后,终于配置好了环境,然后按老师的要求,根据敏捷开发方法,进行测试驱动,持续集成,结对编程。也写了backlog。
前期的东西都搞的差不多了终于开始写代码了,写啊写,PHP不熟,sql不熟,一个sql写十几次总算勉强成功取出数据,PHP里面超级简单的函数也要依赖Google。队长看到如此速度,很是纠结,于是放话:测试个毛啊!直接写了,这速度。这样我们就放弃了测试驱动。之后还剩下,结对编程,结对编程这东西,确实要结对,不是一个人说结对就能结对的,所以由于奇数原因,结对也很失败,个人来看吧!还是很喜欢结对编程的,不是因为可以偷懒,是因为它真的能省时(写程序大部分时间用在调试上,结对bug少很多)。有的东西不是喜欢就可以做的,无奈结对编程失败。持续集成呢!因为PHP直接运行不需要部署,我们成天都在集成。还有那个backlog,认真想想,如果要管理项目的进度,还是很有用的,还是因为我们的项目不大的原因,项目进度看看代码就知道了。那个也就是应付式的搞搞。
经过我们对开发过程的‘个性化’和‘精化’,最终第一个迭代周期到了,拿去给老师评审,老师看到代码结构,严重批评了我们项目的设计,看出来了我们都没设计,没对数据库进行封装,没reuse,应对变更的能力很弱,可维护性低,如此对于现在的需求做起来貌似不难,但是以后系统变复杂以后会变得不可维护。虽然老师一般都是抱着批判的态度来评审的,但是这里也确实说到我们几个很严重的问题,特别是对数据库的封装(嗯。。貌似这里要接近今天讲的主题了)。
由于上面的问题,我们决定对代码进行重构,既然重构,那我们还是回到zend的怀抱吧(开始我和yongxiu同学准备用zend)!于是我们在项目中期进行学习,学习zend,因为项目中各部分的逻辑在前期已经做的差不多,重构的主要任务就是把以前的东西和zend的框架融合一下,使得它更加MVC一点,使用zend的提供的数据库相关类,把封装数据库的重任交给了zend。如此,我就开始zend啊zend,最后在zend的多表联查哪里卡住,到网上搜zend 多表联查的例子,大多都是用zend手册里面的那个bugs,accounts,bugproducts,products的例子,不是说那个例子不好,只是那个例子太简单,往往没项目上面套完全不能满足需求,另外一个多表联查的例子是只有恋歌表的用jion的那个。可能是因为个人智商比较低的原因,看了总感觉迷迷糊糊的,不懂。而且它只是两个表联接,不满足需求,我也试着根据它的例子改成三表联查的,改完总是出现各种奇奇怪怪的问题,也就是没成功。继续Google,甚至看到好多人怀疑zend有bug,我开始迷惑,其实我想这样的框架,不应该在这种常用的东西上面出bug吧!我不愿相信,也不太相信,但是我遇到的问题又逼着我相信。这样我最后查不到,试不出来,只能主动出击——到csdn上面问,有人回帖了,首先不论如何,要谢谢回帖的朋友,他说怎地不能联表查!只能用sql,我看看他的头像下面还有个什么奖牌什么的,所以还是有些相信他,觉得是牛人,我开始在zend里面用sql。用了一个晚上,今天回来之后不知道为什么,突然还是很想用zend联表查询,其实我心底一直认为zend是可以多表联查的。(我的妈呀!这么多了,终于到正文了)。
.假设现在有4张表(作为例子,应该够多了吧!对本例无用的列被删除)其实这表的联接也算比较复杂了,主要是因为我搜到的例子太简单,所以来个复杂的
user(user_id, user_uname)//user_id是主键,其他表类似 company(com_id, com_cname) city(city_id, city_name) user_com_city(user_id, com_id, city_id )//和相对应的表有外键的关系,当然不是必须的,表示用户在某个公司某地的工作记录 school (school_id, school_name)//学校 user_school(user_id, school_id)//表示user的毕业学校
表终于敲完了,敲死我鸟。。
好了,下面假设知道一个$city_id = ,知道一个$com_id,要查在这个公司这个地点的用户,还要看看他毕业的学校,那我们直接用sql就会这样写:
SELECT * FROM `user` u, company c, city ct, user_com_place ucp, user_school us, school s WHERE ct.city_id = $city_id AND c.com_id = $com_id AND ucp.city_id = ct.city_id AND ucp.user_id = u.user_id AND ucp.com_id = c.com_id AND us.school_id = s.school_id AND us.user_id = u.user_id;
通过这个sql就可以查处满足上述要求的用户的所有相关信息,注意上面用了*,实际使用过程中还是少用的好,就在写的过程我为了这句sql不至于太长,改成*结果,明显感觉查询速度变慢了很多。
下面我们来看看用zend里的Zend_Table_Select怎么来构造一个可以完成这个任务的$select:
//首先获得$adapter, $adapater = Zend_Db_Table::getDefaultAdapter(); $select = $adapater->select()//得到一个Zend_Table_Select ->from(array(‘ct’=>’city’), array(‘city_name’=>’ct.sity_name’)) //这的from函数第二个参数,是指示要取的columns,如果没有这,是取出全部数据,也就是上面使用的*, 关于from函数详情见 //zend 手册,这里array(‘city_name’=>’ct.name’)就相当于sql里面的ct.name AS city_name给st.city_name取了个别名 ->from(array(‘u’=>’user’), array(‘uname’=>’u.user_name’)) //同上 ->from(array(‘c’=>’company’), array(‘cname’=>’c.com_name’)) //同上 ->from(array(‘s’=>’school’), array(‘sname’=>’s.school_name’)) //同上 ->join(array(‘ucp’=>’user_com_city’), ‘ct.city_id = ucp.city_id and ucp.user_id = u.user_id and ucp.com_id = c.com_id’, ”) //使用join,第二个参数默认是*全取,这里使用”说明不去任何数据 ->join(array(‘us’=>’user_school’), ’u.user_id = us.user_id and s.school_id = us.school_id’, ”) ->where(‘c.com_id = ‘.$com_id.’ AND ct.city_id = ‘.$city_id); //这里是额外限制条件 下面详细说明一下上面的代码:首先使用adapter的select()方法得到一个Zend_Table_Select,之后的from()方法,这一连串的from说明了我们要从那些表中取出数据,后面的join()里面放置关联的数组和要使用的关联规则, 如:u.user_id = us.user_id and s.school_id = us.school_id’,之后使用where增加我们需要的其他限制条件,后面可以继续增加order(), limit()等等函数来增加其他限制,这里需要注意的几点是: 1.要从那些表取数据,先在前面用from列出来 2.join里面的关联表,后面定义的关联规则一定要是与前面关联表相关的,里面使用到的表一定是上面from里面或者join里面出现过的 3.各个函数的顺序(开始的时候,我就是因为我几个函数不太清楚,瞎组合,最后悲剧了很久)
这就是纠结了我三天的东西,现在看来如此简单,当初。。。。。,无语了,刚才搞成功了,高兴得我……,那种快乐,真的无法形容,总感觉那种解决了一个纠结自己很久的问题的快乐是程序员独有的。现在好多了,刚才实在太兴奋了。
哦,差点忘了,如果对上述的有什么问题,q我:723943634(几乎全天在线),e-mail:[email protected], 我也刚开始接触PHP,刚开始接触zend,刚开始写博客。有问题大家一起探讨探讨。:)