当框架限制了我的想法,我选择Hack
自框架出现以来,从来就不乏这方面的讨论,比如《Java程序员的堕落》。一方面,框架大大简化便利了开发;另一方面,又因框架做了太多的封装,让我们失去了很多深入的机会,或者一旦遇到一些莫名其妙的问题就容易陷入困境。
那么应不应该使用框架?我想这个问题不是个人所能回答的。更实际的问题是,如何利用好框架?
我的web学习经历是最开始写纯粹html,接着css,不久接触web标准,随后学习js,然后不满足于静态页而开始学习php。
学习php开始很长一段时间都是用的php内嵌sql再echo html(如果不是一开始就使用框架的话,这是学习php的毕竟之路了),往后开始做一些项目。开始是简单的投票系统,接着是图文直播系统、网络课程,到现在的教室安排系统。规模从小到大、由简单到复杂,在这个过程中,我开始意识到,原始的php开发模式已经无法适应大量而复杂的项目了。如果不采取一些措施对代码进行有效的组织,那么光是解决一些简单而又重复的问题就可以把人累死。
借此开始接触MVC,并按照自己的理解形成了一套面向过程的MVC。有了一个简单的框架,开发变得有序多了,而且具有很好的扩展性。
回顾php的框架史,早在php具备面向对象特性之前就出现了各种框架,但并不形成气候,大多人还是宁愿使用自己的框架。直到php具备了面向对象特性,各种框架才如雨后春笋般诞生并形成了不同规模的社区。这里有个事实,面向对象的MVC框架局限性太大。就我个人来说,自己的那套面向对象MVC框架只是简单的分层而已,很多重复的工作并没有得到简化。
那么我要自己实现一个面向对象的MVC框架么,面对现在这么多php框架,为什么还要自己实现呢?
即使不是自己实现,面对现在数量如此之多的php框架还是很令人头疼的,不过想想实在没有必要过多的纠结,我本来就没打算今后只使用一个php框架,作为入门和学习我选择了ThinkPHP。
回到最初的问题,如何利用好框架,在我看来,我们应该拥抱框架(当然,根据实际情况,也有不用框架的时候),利用框架加快开发和方便维护才是实际的,但与此同时我们也要做好Hack框架的准备,有时为了突破框架的限制,我们需要采取一些特别的手段甚至改写框架源代码(这也是开源的意义不是么)。
突破ThinkPHP关系模型单层限制
最近开始使用ThinkPHP开发项目,但在使用的过程中遇到了一个小问题,ThinkPHP的关系模型只支持一层关系,这个问题其他人也发现并提出了。
递归的关系模型是很有价值的,并且项目中确实要用到,然而官方的RelationModel没有考虑到这点。
最坏的打算是改写ThinkPHP/Extend/Model/RelationModel.class.php,使其可以递归的处理多层关系。但阅读RelationModel的实现代码后想到,只要继承原RelationModel,并重写查询方法,对每个查询语句添加relation(true),这样通过原RelationModel,新的RelationModel就可以递归的处理多层关系了。
这是原RelationModel的源代码:
classRelationModelextendsModel{protectedfunction getRelation(&$result,$name='',$return=false){
$model = D($mappingClass);switch($mappingType){case HAS_ONE:
$pk = $result[$mappingKey];
$mappingCondition .=" AND {$mappingFk}='{$pk}'";
$relationData = $model->where($mappingCondition)->field($mappingFields)->find();break;
我的解决是新建一个_ReletionModel,继承自RelationModel,重写getRelation方法:
class_RelationModelextendsRelationModel{protectedfunction getRelation(&$result,$name='',$return=false){
$model = D($mappingClass);switch($mappingType){case HAS_ONE:
$pk = $result[$mappingKey];
$mappingCondition .=" AND {$mappingFk}='{$pk}'";
$relationData = $model->relation(true)->where($mappingCondition)->field($mappingFields)->find();break;
使用新的_RelationModel创建出来的数据模型就可以递归处理多层关系了。
Bootstrap的modal无法实现不同remote的适配器
在我的项目中有一个表格,我希望通过bootstrap的modal ajax获取<a>标签href所指向的页面,简单的做法是使用bootstrap提供的DOM API,每个<a>标签的data-target指向同一个modal元素(所谓的适配器模式),这样避免了大量的js代码,却不想引入了新问题。
我遇到的问题可以简单用以下代码描述:
<aid="a"data-target="#modal">a</a><aid="b"data-target="#modal">b</a><divid="modal"class="modal hide fade"><divclass="modal-header"><buttontype="button"class="close"data-dismiss="modal"aria-hidden="true">×</button><h3>Title</h3></div><divclass="modal-body"></div><divclass="modal-footer"><buttonclass="btn"data-dismiss="modal"aria-hidden="true">关闭</button></div></div>
当点击a链接,弹出的是a所指向的页面,但点击b链接还是弹出a所指向页面,这显然不是我想要的。
尝试过多种方法无果后,最后决定从bootstrap.js源代码下手。
/* MODAL PLUGIN DEFINITION
* ======================= */
$.fn.modal =function(option){returnthis.each(function(){var $this = $(this), data = $this.data('modal'), options = $.extend({}, $.fn.modal.defaults, $this.data(),typeof option =='object'&& option)if(!data) $this.data('modal',(data =newModal(this, options)))if(typeof option =='string') data[option]()elseif(options.show) data.show()})}/* MODAL DATA-API
* ============== */
$(document).on('click.modal.data-api','[data-toggle="modal"]',function(e){var $this = $(this), href = $this.attr('href'), $target = $($this.attr('data-target')||(href && href.replace(/.*(?=#[^\s]+$)/,'')))//strip for ie7, option = $target.data('modal')?'toggle': $.extend({ remote:!/#/.test(href) && href }, $target.data(), $this.data())
e.preventDefault()
$target
.modal(option).one('hide',function(){
$this.focus()})})
可以看到,bootstraup的modal通过jquery的data方法存储实例化的modal对象,下次调用会判断是否已经实例化,如果已实例化,则使用已实例化的对象。
现在我需要对于不同的href重新实例化,显然,只要添加一个判断条件即可
……if(!data ||(options.remote && data.options.remote != options.remote)) $this.data('modal',(data =newModal(this, options)))……, option = $target.data('modal')&& $target.data('modal').href == href ?'toggle': $.extend({ remote:!/#/.test(href) && href }, $target.data(), $this.data())

浙公网安备 33010602011771号