zoukankan      html  css  js  c++  java
  • 当框架限制了我的想法,我选择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的源代码:

    
    class RelationModel extends Model {
    	protected function 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 _RelationModel extends RelationModel {
        protected function 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代码,却不想引入了新问题。

    我遇到的问题可以简单用以下代码描述:

    
    <a id="a" data-target="#modal">a</a>
    <a id="b" data-target="#modal">b</a>
    <div id="modal" class="modal hide fade">
    	<div class="modal-header">
    		<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
    		<h3>Title</h3>
    	</div>
    	<div class="modal-body"></div>
    	<div class="modal-footer">
    		<button class="btn" data-dismiss="modal" aria-hidden="true">关闭</button>
    	</div>
    </div>
    

    当点击a链接,弹出的是a所指向的页面,但点击b链接还是弹出a所指向页面,这显然不是我想要的。

    尝试过多种方法无果后,最后决定从bootstrap.js源代码下手。

    
     /* MODAL PLUGIN DEFINITION
      * ======================= */
    
      $.fn.modal = function (option) {
        return this.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 = new Modal(this, options)))
          if (typeof option == 'string') data[option]()
          else if (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 = new Modal(this, options)))
    ……
    , option = $target.data('modal') && $target.data('modal').href == href ? 'toggle' : $.extend({ remote:!/#/.test(href) && href }, $target.data(), $this.data())
    ……
    
  • 相关阅读:
    Unity入门教程(上)
    牛课堂算法直播题目
    使用3ds Max制作简单卧室
    Aizu_Insertion Sort
    C语言中的循环语句练习
    3ds Max 中的导航控件SteeringWheels入门介绍
    3ds Max 中的导航控件ViewCube入门介绍
    容易出错的 if 语句
    计蒜客2018 蓝桥杯省赛 B 组模拟赛(一)
    浅谈图的广度优先遍历
  • 原文地址:https://www.cnblogs.com/7c00/p/2909993.html
Copyright © 2011-2022 走看看