用户
 找回密码
 入住 CI 中国社区
搜索
查看: 3737|回复: 5
收起左侧

[Others] 关于视图自动输出讨论

[复制链接]
发表于 2014-2-11 14:08:18 | 显示全部楼层 |阅读模式
本帖最后由 kinwyb 于 2014-2-15 10:34 编辑

问题:
      
昨天整理网站代码,发现控制器中的视图输出基本都是$this->load->view。这样每个控制器方法要输出的时候都需要重复的写这视图输出代码,如果视图输出出现修改(比如要使用一个模版解析啦)那么所有的都需要一个个的修改。太麻烦了
     因此我想到了视图的统一自动输出。在CI流程中,当控制器代码执行完成后自动调用视图统一的一个输出方法来输出视图。而不要把视图输出写到控制器中。这样即可以省去重复的写视图输出代码,也可以方便的修改视图输出方式。

我的解决方式
     要在CI流程中加入一个视图自动输出环节。可以使用CI钩子实现,但是因为钩子是单独的一个进程来实现处理的。所以无法调用到控制器中的数据。次方法行不通(PS:本人对钩子使用不多,自会最基本的运用。要是有高手能用钩子实现此功能,希望能把代码贴出来学习下)
    既然钩子不行,我就去修改了CI的核心源码。在源码CodeIgniter.php中加入一个函数调用来实现该功能。(在CI源码359行左右)
PHP复制代码
 
call_user_func_array(array(&$CI, $method), array_slice($URI->rsegments, 2));//在后面加入自己写的代码
//添加一个控制器执行结束后的自动调用函数
 if(method_exists($CI, "_back"))
 {
            $CI->_back();
  }
 
复制代码

     在CI调用控制器方法后,检测当前控制器是否存在一个_back方法,如果存在执行该方法。把视图输出的代码写在这。这样就能在执行完控制器后自动执行视图输出了。当然为了达到此功能还需要重写controller类
PHP复制代码
 
<?php
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class MY_Controller extends CI_Controller
{
    /**
     * 视图输出数据
     * @var 数组
     */

    protected $data;
    /**
     * 是否结束页面
     * @var 是/否
     */

    protected $end=false;
    /**
     * 指定视图页面
     * @var 字符串
     */

    protected $view;
 
    public function __construct()
    {
        parent::__construct();
    }
 
    //结束后由系统调用
    function _back()
    {
        if(!$this->end)
            if(empty($this->view))
                $this->load->view(get_called_class().'_view/'.$this->uri->segment(2,'index'),$this->data);
            else
                $this->load->view($this->view,$this->data);
    }
   
}
 
复制代码


问题
      当我把这个想法发到CI微信群后,热心群友就提出了几个问题,我在上面扩写的controller里基本把有的问题解决了一下
      1. 不是每个控制器都需要视图输出,比如ajax:
           解决:在controller类里有有一个end变量控制是否需要视图输出,当不需要视图输出的时候,只需要在控制器方法里指定end为true,即可。
      2. 选择性视图输出:
          解决:因为在自动输出的时候是,视图文件是指定的views/控制器_view/方法名.php(这是我指定的视图文件存放规则,可以随便修改)。但是有些情况你可以存放视图路径不在这里。或者是要公用视图文件,那么你可以在控制器方法中指定的视图文件给view变量。如果view不为空,那么就会加载view变量里的文件,而不是自动指定的文件。
      3. 视图输出顺序:
           解决:
              1.视图输出顺序的确是一个问题。简单的可以在视图文件中通过$this->load->view来解决。
              2.本人现在的解决方法,因为我是用了HEX大神版本的HMVC,所以我把公共部分都放到了module里,然后在在视图文件里调用module来实现的,所以这个问题基本不存在。

注意:
     因为统一了自动输出,所以输出的数据就要统一一个变量存放。类似我的代码,那么就要统一把输出数据存放到data数组中。

好处:
    统一了输出方法,好处就是可以方便的修改输出方式,比如我要把直接的view输出,改成用模版解析的输出,那么只需要修改这个_blank函数里的输出即可。无需去修改控制器里的内容。要是你现在特定的控制器中使用特定的输出方法,那么可以在控制器里复写_blank函数实现。因为_blank函数在控制器中所以可以方便的调用控制器中所有的变量,方法。

缺点:
   本人实现过程中修改了源码这是一个问题,如果源码升级那就得要在次修改源码才行。不过,HEX大神说可以在不修改源码的情况下实现。尽情期待吧!

2014-2-15:已经可以不修改源码实现此功能了。详情见3楼!!

欢迎大家讨论!集思广益

CI微信群二维码:
mmexport1392098519675.jpeg

评分

参与人数 1威望 +5 收起 理由
Hex + 5 赞一个!

查看全部评分

发表于 2014-2-11 14:31:25 | 显示全部楼层
good           
发表于 2014-2-11 15:59:43 | 显示全部楼层
不明觉厉
 楼主| 发表于 2014-2-15 10:33:08 | 显示全部楼层
对于钩子了解后,发现可以是有钩子实现此功能,以免修改源码使得框架升级麻烦。
建立一个post_controller的钩子。在钩子中获取CI实例,然后运行_back方法即可。。当然扩展controller是必须的
发表于 2014-2-15 17:47:20 | 显示全部楼层
感觉还是页面信息归纳的不够多吧。。。一般也不需要几个页面,而且各个页面之间差别还挺大的。。。。
发表于 2014-4-3 17:50:06 | 显示全部楼层
good   

本版积分规则