可参考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);?>