xyst0524 发表于 2012-11-21 16:41:47

页面布局layout,实现非views下视图的加载

       今天学了一下CI的页面布局layout,很好用,谢谢哈。原帖网址:http://codeigniter.org.cn/forums/forum.php?mod=viewthread&tid=1176,再次感谢!
       但是以前用其他开发者写的框架的时候,发现他们的layout不是写在views下的,于是就想看看CI能不能也可以实现views目录以外的目录下视图的加载。
       ....
       终于,可以实现了。麻烦大家看看哈,不好之处请多多指教。
方法一:
1,在application/core下扩展核心类load(具体见手册),如:
class MY_Loader extends CI_Loader {
2,重写view方法:
function view($view, $vars = array(), $return = FALSE, $layout = FALSE)
{
if ($layout) //加载布局页面
{
$ext = pathinfo($view, PATHINFO_EXTENSION);
$view = ($ext == '') ? $view.EXT : $view;
$path = APPPATH.'layout/'.$view; //layout目录下的视图
return $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_object_to_array($vars), '_ci_path' => $path, '_ci_return'
$return));
}
else
{
return $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_object_to_array($vars), '_ci_return' => $return));
}
}
3,页面布局layout类(library目录)中的view方法:
   function view($view, $data1=null, $return=false, $layout = TRUE) //$layout参数传递给扩展核心类my_load.
{
$data2['content_for_layout'] = $this->obj->load->view($view,$data1,true); //内容页,如同在视图中输出数据,不同的是此数据为一个内容页面

if($return)
{
$output = $this->obj->load->view($this->layout,$data2, true, $layout);
return $output;
}
else
{
$this->obj->load->view($this->layout,$data2, false, $layout); //视图(布局)下的视图($data2的索引下包括内容视图及$data1)
}
}
//4,可参考module(hmvc架构)类对$layout进行动态赋值。

方法二:
1,同方法一第1步
2,添加属性:var $_ci_is_inside_layout = FALSE; // 判断是否调用布局
3,添加方法:
public function _ci_layout_ready()
{
$this->_ci_is_inside_layout = TRUE;
}
4,重写view方法:
function view($view, $vars = array(), $return = FALSE)
{
if ($this->_ci_is_inside_layout) //加载布局页面
{
$ext = pathinfo($view, PATHINFO_EXTENSION);
$view = ($ext == '') ? $view.EXT : $view;
$path = APPPATH.'layout/'.$view;
return $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_object_to_array($vars), '_ci_path' => $path, '_ci_return'
=> $return));
}
else
{
return $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_object_to_array($vars), '_ci_return' => $return));
}
}

5,页面布局layout类(library目录)中的view方法:
   function view($view, $data1=null, $return=false)
{
//$this->obj->load->_ci_layout_ready();//切记不能在此处调用。按代码先后执行的顺序是先执行下面一行的view,但是此view是要加载views目录下的视图,若取消
注释该行则执行下面一行的view方法后会跳到自己设定的目录下寻找视图。
$data2['content_for_layout'] = $this->obj->load->view($view,$data1,true); //内容页,如同在视图中输出数据,不同的是此数据为一个内容页面
$this->obj->load->_ci_layout_ready();
if($return)
{
$output = $this->obj->load->view($this->layout,$data2, true);
return $output;
}
else
{
$this->obj->load->view($this->layout,$data2, false); //视图(布局)下的视图($data2的索引下包括内容视图及$data1)
}
}


liuhejia460 发表于 2012-11-21 16:59:01

好贴,学习了,过两天就要用到这个

xyst0524 发表于 2012-11-21 17:24:03

liuhejia460 发表于 2012-11-21 16:59 static/image/common/back.gif
好贴,学习了,过两天就要用到这个

嗯,多多交流哈,我也刚学这个。

liuhejia460 发表于 2012-11-21 17:32:40

xyst0524 发表于 2012-11-21 17:24 static/image/common/back.gif
嗯,多多交流哈,我也刚学这个。

好的~~~多多交流

paperen 发表于 2012-11-22 01:17:05

多谢分享~~正好最近碰到这个问题 我用的是hex的HMVC

我直接将你这个layout加到MY_Loader.php中

    // --------------- Layout extends --------------

    private $layout = 'default';

    public function _ci_layout_ready() {
      $this->_ci_is_inside_layout = TRUE;
    }

    public function set_layout( $layout ) {
      $this->layout = $layout;
    }

    public function layout( $view, $data1 = null, $return = false ) {
         //内容页,如同在视图中输出数据,不同的是此数据为一个内容页面
      $data2['content'] = $this->view( $view, $data1, true );
      $this->_ci_layout_ready();
      if ( $return ) {
            $output = $this->view( $this->layout, $data2, true );
            return $output;
      } else {
            //视图(布局)下的视图($data2的索引下包括内容视图及$data1)
            $this->view( $this->layout, $data2, false );
      }
    }


其中需要修改一下MY_Loader.php的view方法

    function view($view, $vars = array(), $return = FALSE)
    {
      if ($this->_ci_is_inside_layout)
      {
            //加载layout页面
            $ext = pathinfo($view, PATHINFO_EXTENSION);
            $view = ($ext == '') ? $view.EXT : $view;
            $path = APPPATH.'layout/'.$view;
            return $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_object_to_array($vars), '_ci_path' => $path, '_ci_return'
            => $return));
      } else if ($this->_ci_is_inside_module) {
            //加载module中的views
            $ext = pathinfo($view, PATHINFO_EXTENSION);
            $view = ($ext == '') ? $view.EXT : $view;
            $path = APPPATH.'modules/'.$this->_ci_module_path.'/views/'.$view;

            if (file_exists($path))
            {
                return $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_object_to_array($vars), '_ci_path' => $path, '_ci_return' => $return));
            }
            else
            {
                return $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_object_to_array($vars), '_ci_return' => $return));
            }
      }
      else
      {
            return $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_object_to_array($vars), '_ci_return' => $return));
      }
    }


在application目录下创建layout/default.php

<h3>header</h3>
<?php echo $content; ?>
<h3>footer</h3>


模块控制器调用视图时写成

// index为该模块views目录下的index.php视图文件
$this->load->layout( 'index' );

xyst0524 发表于 2012-11-22 10:17:20

paperen 发表于 2012-11-22 01:17 static/image/common/back.gif
多谢分享~~正好最近碰到这个问题 我用的是hex的HMVC

我直接将你这个layout加到MY_Loader.php中


呵呵,都写到一起去了。要是再扩展layout的话是不是有点臃肿啊?

paperen 发表于 2012-11-22 20:54:53

xyst0524 发表于 2012-11-22 10:17 static/image/common/back.gif
呵呵,都写到一起去了。要是再扩展layout的话是不是有点臃肿啊?

好吧 我还是放出来吧 谢谢提醒

smallhe 发表于 2013-1-21 09:53:42

学习 .。。学习!

`NoCareFree` 发表于 2013-1-25 17:39:03

可以学习下 magento 的写法.. layout 调用 block ,block 调用 (block跟 数据) 嵌套式的,自己一直写不出来,有点麻烦。有需要的朋友可以去了解下,觉得很不错 magento 的不一样的mvc机制
页: [1]
查看完整版本: 页面布局layout,实现非views下视图的加载