今天修补一个老项目中,使用的是TP框架,到视图区发现对象无法遍历输出。真够郁闷的,对于不喜欢数组喜欢变量的强迫症来说就得琢磨琢磨。搞了半天,搜了半天没找到满意的结果。之后顺道去了下官网的手册看了看,寥寥几行说明,真是醉了。
TP默认视图循环代码
<foreach name="apidatas" item="val"> {$val.sta_name} //这是默认输出数组的方式 </foreach>
打开他生成后的缓存文件,里面对应生成的代码。(Rumtime/Cache/*****.php)
<?php if(is_array($val->goods_list)): foreach($val->goods_list as $key=>$v): ?> //后面略
这娘的直接就跳过了。
搜索一下关键词is_array 到T hinkPHP\Library\Think\Template\TagLib\Cx.class.php文件里面的_foreach 方法
给添加上对象的判断,修改后代码奉上。
/** * foreach标签解析 循环输出数据集 * @access public * @param array $tag 标签属性 * @param string $content 标签内容 * @return string|void */ public function _foreach($tag,$content) { $name = $tag['name']; $item = $tag['item']; $key = !empty($tag['key'])?$tag['key']:'key'; $name = $this->autoBuildVar($name); //额外增修对象输出方式 //author:编程大哥 $parseStr = '<?php if(is_array('.$name.') || is_object('.$name.')): foreach('.$name.' as $'.$key.'=>$'.$item.'): ?>'; $parseStr .= $this->tpl->parse($content); $parseStr .= '<?php endforeach; endif; ?>'; if(!empty($parseStr)) { return $parseStr; } return ; }
本想着是不是再增修下对象变量的引用方式
PHP对象的指向符是 -> 由于右侧是“>”符号会跟其他标签冲突,也就导致了很多人都经常报的一个
XML标签语法错误
研究后发现只需要更改视图页对象变量的引用方式即可 由 "->" 换到 ":"
此处是在内置的尖括号<>标签内使用 : 代替-> 若是在 大括号{} 标签内也可使用->
<foreach name="apidatas" item="val"> {$val:sta_name} //这是默认对象的引用方式 </foreach>
TP视图页变量引入方式
{$user_name} 普通变量
{$user.user_name} 数组成员引用方式
{$user:user_name} 对象成员饮用方式
foreach 标签修改见上文!
增加变量标签解析支持数组对象混合制
譬如:{$store.goods_list:goods_info.goods_name}
解析为:$store['goods_list']->goods_info['goods_name']
以上为 数组 对象 数组 顺序解析法 首个为数组,数组对象混合变量一般情况下不会出现这种状况,也很少去用,如果遇到了也比较奇葩,在此记录解决方案。当然也可以直接写PHP代码实现!
修改文件 \ThinkPHP\Library\Think\Template.class.php
方法:parseVar
修改后的方法如下
/** * 模板变量解析,支持使用函数 * 格式: {$varname|function1|function2=arg1,arg2} * @access public * @param string $varStr 变量数据 * @return string */ public function parseVar($varStr){ $varStr = trim($varStr); static $_varParseList = array(); //如果已经解析过该变量字串,则直接返回变量值 if(isset($_varParseList[$varStr])) return $_varParseList[$varStr]; $parseStr = ''; $varExists = true; if(!empty($varStr)){ $varArray = explode('|',$varStr); //取得变量名称 $var = array_shift($varArray); if('Think.' == substr($var,0,6)){ // 所有以Think.打头的以特殊变量对待 无需模板赋值就可以输出 $name = $this->parseThinkVar($var); }elseif( false !== strpos($var,'.')) { //支持 {$var.property} $vars = explode('.',$var); $var = array_shift($vars); switch(strtolower(C('TMPL_VAR_IDENTIFY'))) { case 'array': // 识别为数组 $name = '$'.$var; //增修支持数组对象混合 @编程大哥 [start] foreach ($vars as $key=>$val){ $tmp = ''; if(strpos($val,':')){ $vars_obj = explode(':',$val); $val = $vars_obj[0]; unset($vars_obj[0]); foreach($vars_obj as $ov) $tmp .= '->'.$ov; } $name .= '["'.$val.'"]'.$tmp; } //增修支持数组对象混合 @编程大哥 [end] break; case 'obj': // 识别为对象 $name = '$'.$var; foreach ($vars as $key=>$val) $name .= '->'.$val; break; default: // 自动判断数组或对象 只支持二维 $name = 'is_array($'.$var.')?$'.$var.'["'.$vars[0].'"]:$'.$var.'->'.$vars[0]; } }elseif(false !== strpos($var,'[')) { //支持 {$var['key']} 方式输出数组 $name = "$".$var; preg_match('/(.+?)\[(.+?)\]/is',$var,$match); $var = $match[1]; }elseif(false !==strpos($var,':') && false ===strpos($var,'(') && false ===strpos($var,'::') && false ===strpos($var,'?')){ //支持 {$var:property} 方式输出对象的属性 $vars = explode(':',$var); $var = str_replace(':','->',$var); $name = "$".$var; $var = $vars[0]; }else { $name = "$$var"; } //对变量使用函数 if(count($varArray)>0) $name = $this->parseVarFunction($name,$varArray); $parseStr = '<?php echo ('.$name.'); ?>'; } $_varParseList[$varStr] = $parseStr; return $parseStr; }
以上修改后方法只支持先数组后对象方式,想要更奇葩的可以自己研究后发出来哦!