zoukankan      html  css  js  c++  java
  • php CI框架高级视图功能,视图继承,多重继承,视图片段

    可参考http://codeigniter.org.cn/forums/thread-8949-1-1.html

    我这里是从项目代码里总出来的:

    1、首先在application/core文件夹下增加MY_Loader.php文件。只要增加这个类就可以,其他操作不变,在视图文件中就可以使用视图继承了。

    文件内容如下:

      1 <?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
      2 
      3 /**
      4  * Loader Extend Class
      5  *
      6  * Loads views and files
      7  *
      8  * @package        CodeIgniter
      9  * @subpackage    Libraries
     10  * @author        Kth007#gmail.com
     11  * @category    Loader
     12  * @link        http://codeigniter.org.cn/forums/viewthread.php?tid=8949
     13  */
     14 class MY_Loader extends CI_Loader
     15 {
     16 
     17     /**
     18      * 视图堆栈
     19      *
     20      * @var array
     21      */
     22     private $_stacks = array();
     23 
     24     /**
     25      * 当前处理的视图
     26      *
     27      * @var int
     28      */
     29     private $_current;
     30 
     31     /**
     32      * 视图的继承
     33      *
     34      * @param string $tplname
     35      *
     36      * @access protected
     37      */
     38     protected function _extends($tplname)
     39     {
     40         $this->_stacks[$this->_current]['extends'] = $tplname;
     41     }
     42 
     43     /**
     44      * 开始定义一个区块
     45      *
     46      * @param string $block_name
     47      * @param mixed $config
     48      *
     49      * @access protected
     50      */
     51     protected function _block($block_name, $config = null)
     52     {
     53         $stack =& $this->_stacks[$this->_current];
     54         if (!empty($stack['blocks_stacks']))
     55         {
     56             // 如果存在嵌套的 block,则需要记录下嵌套的关系
     57             $last = $stack['blocks_stacks'][count($stack['blocks_stacks']) - 1];
     58             $stack['nested_blocks'][] = array($block_name, $last);
     59         }
     60         $this->_stacks[$this->_current]['blocks_config'][$block_name] = $config;
     61         array_push($stack['blocks_stacks'], $block_name);
     62         ob_start();
     63     }
     64 
     65     /**
     66      * 结束一个区块
     67      *
     68      * @access protected
     69      */
     70     protected function _endblock()
     71     {
     72         $block_name = array_pop($this->_stacks[$this->_current]['blocks_stacks']);
     73         $this->_stacks[$this->_current]['blocks'][$block_name] = ob_get_clean();
     74         echo "%block_{$block_name}_{$this->_stacks[$this->_current]['id']}%";
     75     }
     76 
     77 
     78     /**
     79      * 载入一个视图片段
     80      *
     81      * @param string $element_name 视图名称
     82      * @param array $vars
     83      *
     84      * @access protected
     85      */
     86     protected function _element($element_name, array $vars = null)
     87     {
     88         $file_exists = FALSE;
     89         $filename = '';
     90         foreach ($this->_ci_view_paths as $view_file => $cascade)
     91         {
     92             $filename = $view_file.$element_name.EXT;
     93             if ( ! file_exists($filename))
     94             {
     95                 $file_exists = FALSE;
     96             }else{
     97                 $file_exists = TRUE;break;
     98             }
     99         }
    100         if(!$file_exists){
    101             show_error('Unable to load the requested file: '.$filename);
    102         }else{
    103             extract($this->_ci_cached_vars);
    104             if (is_array($vars)) extract($vars);
    105             include($filename);
    106         }
    107     }
    108 
    109     /**
    110      * Loader
    111      *
    112      * 这个函数用来加载视图或者文件.
    113      * 这个函数改写 CI_Loader 类内函数,使其支持视图继承和多重继承。
    114      *
    115      * @access    private
    116      * @param    array
    117      * @return    void
    118      */
    119     function _ci_load($_ci_data)
    120     {
    121         // 设置默认的数据变量
    122         foreach (array('_ci_view', '_ci_vars', '_ci_path', '_ci_return', '_ci_viewid', '_ci_stack') as $_ci_val)
    123         {
    124             $$_ci_val = ( ! isset($_ci_data[$_ci_val])) ? FALSE : $_ci_data[$_ci_val];
    125         }
    126 
    127         // 设置请求文件的路径
    128         if ($_ci_path != '')
    129         {
    130             $_ci_x = explode('/', $_ci_path);
    131             $_ci_file = end($_ci_x);
    132         }
    133         else
    134         {
    135             $_ci_ext = pathinfo($_ci_view, PATHINFO_EXTENSION);
    136             $_ci_file = ($_ci_ext == '') ? $_ci_view.'.php' : $_ci_view;
    137 
    138             foreach ($this->_ci_view_paths as $view_file => $cascade)
    139             {
    140                 if (file_exists($view_file.$_ci_file))
    141                 {
    142                     $_ci_path = $view_file.$_ci_file;
    143                     $file_exists = TRUE;
    144                     break;
    145                 }
    146 
    147                 if ( ! $cascade)
    148                 {
    149                     break;
    150                 }
    151             }
    152         }
    153 
    154         if ( ! file_exists($_ci_path))
    155         {
    156             show_error('Unable to load the requested file: '.$_ci_file);
    157         }
    158 
    159         // 这允许任何加载使用 $this->load (views, files, etc.)
    160         // 成为从内部控制器和模型函数访问.
    161 
    162         $_ci_CI =& get_instance();
    163         foreach (get_object_vars($_ci_CI) as $_ci_key => $_ci_var)
    164         {
    165             if ( ! isset($this->$_ci_key))
    166             {
    167                 $this->$_ci_key =& $_ci_CI->$_ci_key;
    168             }
    169         }
    170 
    171         /*
    172          * 提取缓存和变量   也就是把数组下标变成变量
    173          *
    174          * You can either set variables using the dedicated $this->load_vars()
    175          * function or via the second parameter of this function. We'll merge
    176          * the two types and cache them so that views that are embedded within
    177          * other views can have access to these variables.
    178          */
    179         if (is_array($_ci_vars))
    180         {
    181             $this->_ci_cached_vars = array_merge($this->_ci_cached_vars, $_ci_vars);
    182         }
    183         extract($this->_ci_cached_vars);
    184 
    185         //-----by:kth007 20100422------------------------------------------------------------------------------
    186         if ( ! $_ci_viewid) $_ci_viewid = mt_rand();
    187 
    188         $stack = array(
    189         'id'            => $_ci_viewid,
    190         'contents'      => '',
    191         'extends'       => '',
    192         'blocks_stacks' => array(),
    193         'blocks'        => array(),
    194         'blocks_config' => array(),
    195         'nested_blocks' => array(),
    196         );
    197         array_push($this->_stacks, $stack);
    198         $this->_current = count($this->_stacks) - 1;
    199         unset($stack);
    200         //-----------------------------------------------------------------------------------
    201 
    202         /*
    203          * 缓冲输出
    204          *
    205          * We buffer the output for two reasons:
    206          * 1. Speed. You get a significant speed boost.
    207          * 2. So that the final rendered template can be
    208          * post-processed by the output class.  Why do we
    209          * need post processing?  For one thing, in order to
    210          * show the elapsed page load time.  Unless we
    211          * can intercept the content right before it's sent to
    212          * the browser and then stop the timer it won't be accurate.
    213          */
    214         ob_start();
    215 
    216         // If the PHP installation does not support short tags we'll
    217         // do a little string replacement, changing the short tags
    218         // to standard PHP echo statements.
    219 
    220         if ((bool) @ini_get('short_open_tag') === FALSE AND config_item('rewrite_short_tags') == TRUE)
    221         {
    222             echo eval('?>'.preg_replace("/;*\s*\?>/", "; ?>", str_replace('<?=', '<?php echo ', file_get_contents($_ci_path))));
    223         }
    224         else
    225         {
    226             include($_ci_path); // include() vs include_once() allows for multiple views with the same name
    227         }
    228         
    229         
    230         log_message('debug', 'File loaded: '.$_ci_path);
    231 
    232 //-----by:kth007 20100422-----------------------------------------------------------------------------------------------------
    233         $stack = $this->_stacks[$this->_current];
    234         $stack['contents'] = ob_get_clean();
    235 
    236         // 如果有继承视图,则用继承视图中定义的块内容替换当前视图的块内容
    237         if (is_array($_ci_stack))
    238         {
    239             foreach ($_ci_stack['blocks'] as $block_name => $contents)
    240             {
    241                 if (isset($stack['blocks_config'][$block_name]))
    242                 {
    243                     switch (strtolower($stack['blocks_config'][$block_name]))
    244                     {
    245                         case 'append':
    246                             $stack['blocks'][$block_name] .= $contents;
    247                             break;
    248                         case 'replace':
    249                         default:
    250                             $stack['blocks'][$block_name] = $contents;
    251                     }
    252                 }
    253                 else
    254                 {
    255                     $stack['blocks'][$block_name] = $contents;
    256                 }
    257             }
    258         }
    259         // 如果有嵌套 block,则替换内容
    260         while (list($child, $parent) = array_pop($stack['nested_blocks']))
    261         {
    262             $stack['blocks'][$parent] = str_replace("%block_{$child}_{$_ci_viewid}%",
    263             $stack['blocks'][$child], $stack['blocks'][$parent]);
    264             unset($stack['blocks'][$child]);
    265         }
    266         // 保存对当前视图堆栈的修改
    267         $this->_stacks[$this->_current] = $stack;
    268 
    269         if ($stack['extends'])
    270         {
    271             //私有继承.
    272             $filename = "{$stack['extends']}".EXT;
    273                 
    274             return $this->_ci_load(array(
    275                                 '_ci_view' => $filename, 
    276                                 //'_ci_vars' => $this->_ci_cached_vars,
    277                                 '_ci_return' => $_ci_return,
    278                                 '_ci_viewid'=>$_ci_viewid, 
    279                                 '_ci_stack'=>$this->_stacks[$this->_current],
    280             ));
    281         }
    282         else
    283         {
    284             // 最后一个视图一定是没有 extends 的
    285             $last = array_pop($this->_stacks);
    286             foreach ($last['blocks'] as $block_name => $contents)
    287             {
    288                 $last['contents'] = str_replace("%block_{$block_name}_{$last['id']}%",
    289                 $contents, $last['contents']);
    290             }
    291             $this->_stacks = array();
    292             
    293             
    294             if ($_ci_return === TRUE)
    295             {
    296                 @ob_end_clean();
    297                 return $last['contents'];
    298             }
    299 
    300             if (ob_get_level() > $this->_ci_ob_level + 1)
    301             {
    302                 ob_end_flush();
    303             }
    304             else
    305             {
    306                 $_ci_CI->output->append_output($last['contents']);
    307                 @ob_end_clean();
    308             }
    309 
    310         }
    311 //--------------------------------------------------------------------------------------------
    312 
    313         
    314         // Return the file data if requested
    315 /*        if ($_ci_return === TRUE)
    316         {
    317             $buffer = ob_get_contents();
    318             @ob_end_clean();
    319             return $buffer;
    320         }
    321 */
    322         /*
    323          * Flush the buffer... or buff the flusher?
    324          *
    325          * In order to permit views to be nested within
    326          * other views, we need to flush the content back out whenever
    327          * we are beyond the first level of output buffering so that
    328          * it can be seen and included properly by the first included
    329          * template and any subsequent ones. Oy!
    330          *
    331          */
    332 /*        if (ob_get_level() > $this->_ci_ob_level + 1)
    333         {
    334             ob_end_flush();
    335         }
    336         else
    337         {
    338             $_ci_CI->output->append_output(ob_get_contents());
    339             @ob_end_clean();
    340         }
    341 */
    342 
    343 
    344     }
    345 
    346 }
    347 
    348 /* End of file MY_Loader.php */
    349 /* Location: ./application/core/MY_Loader.php */

    2、在视图文件中使用视图继承:

    首先可以在视图中增加一些基础的视图文件作为父视图,以供继承使用,如:view/_layouts/default_layout.php

    代码可参考如下:

     1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
     2 <html xmlns="http://www.w3.org/1999/xhtml">
     3 <head>
     4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
     5 <title><?php $this->_block('title'); ?>我的被别人继承的<?php $this->_endblock(); ?></title>
     6 <script type="text/javascript" src="/static/js/jquery.js"></script>
     7 <script type="text/javascript" src="/static/css/layout.js"></script>
     8 <?php $this->_block('head'); ?><!--这里是载入私有的CSS和JS--><?php $this->_endblock(); ?>
     9 </head>
    10 <body>
    11 <div>这里是头部</div>
    12 <div>这里是导航</div>
    13 <div>这里是左栏</div>
    14 <div><!--这里是内容-->
    15 <?php $this->load->_block('content'); ?><?php $this->load->_endblock(); ?></div>
    16 </div>
    17 <div><?php $this->_block('footer')?> 这里是尾部 <?php $this->_endblick();?></div>
    18 </body>
    19 </html>

    然后在自已的视图里就可以继承这个视图了

    如:

     1         //继承父视图
     2  <?php  $this->_extends('_layouts/default_layout'); ?>
     3  // 重写title
     4  <?php $this->_block('title'); ?>我自己的title,覆盖父类的title<?php $this->_endblock(); ?>
     5  
     6 //重写head部分,可以引入一些自己的JS和CSS,
     7 <?php $this->_block('head'); ?><!--这里是载入私有的CSS和JS--><?php $this->_endblock(); ?>
     8 
     9  //覆盖父视图中的contents部分,这里就可以自定义自己的内容部分了
    10   <?php  $this->_block('contents'); ?>
    11   
    12   <br><br><br><br><br><br>
    13   <center>
    14   <div style="300px;border:1px solid #70B1CD;background:#E0EFF8"><br><br>
    15   <h3 style="color:red;font-size:12px;"><?php echo $message_caption; ?></h3><br>
    16   <p style="color:#000;font-size:12px;">
    17    <?php echo nl2br(htmlspecialchars($message_body)); ?>
    18  </p><br>
    19  <p style="font-size:12px;">
    20    <a href="<?php echo $redirect_url; ?>">如果您的浏览器没有自动跳转,请点击这里</a>
    21  </p><br>
    22  </div>
    23  </center>
    24  <script type="text/javascript">
    25  setTimeout("window.location.href ='<?php echo $redirect_url; ?>';", <?php echo $redirect_delay * 1000; ?>);
    26  </script>
    27 <?php echo $hidden_script; ?>
    28  
    29  <?php  $this->_endblock(); ?>

    还可以载入某个视图片段,方法如下:

    <?php $this->load->_element('topnews', $topnews);?>
  • 相关阅读:
    【BZOJ】2019: [Usaco2009 Nov]找工作(spfa)
    【BZOJ】3668: [Noi2014]起床困难综合症(暴力)
    Redis 字符串结构和常用命令
    Redis实现存取数据+数据存取
    Spring 使用RedisTemplate操作Redis
    使用 java替换web项目的web.xml
    SQL server 从创建数据库到查询数据的简单操作
    SQL server 安装教程
    IntelliJ IDEA 注册码(因为之前的地址被封杀了,所以换了个地址)
    对程序员有帮助的几个非技术实用链接(点我,你不会后悔的)
  • 原文地址:https://www.cnblogs.com/wuheping/p/2789406.html
Copyright © 2011-2022 走看看