Thinkphp修改一句代码,使得foreach标签支持对象,增加变量[数组对象]混合解析法!

今天修补一个老项目中,使用的是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;
    }

以上修改后方法只支持先数组后对象方式,想要更奇葩的可以自己研究后发出来哦!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏魂祭心

原 What Every Dev need

29480
来自专栏Kevin-ZhangCG

[ Java面试题 ]算法篇

210110
来自专栏开发与安全

shell programming tutorial

可以直接 man bash 学习语法和相关命令。 一、什么是shell程序 以文件形式存放批量的Linux命令集合,该文件能够被Shell解释执行,这种文件就是...

19690
来自专栏java一日一条

Java 并发开发:内置锁 Synchronized

在多线程编程中,线程安全问题是一个最为关键的问题,其核心概念就在于正确性,即当多个线程访问某一共享、可变数据时,始终都不会导致数据破坏以及其他不该出现的结果。而...

8720
来自专栏ASP.NETCore

动手实现扩展属性为对象动态添加获取数据(续)

在上一篇文章中我们了解了扩展属性的原理和结构,其实其内部结构与思想都与WPF中的依赖属性基本相同,大家也可以从中了解到关于依赖属性的原理,这对了解及使用依赖属性...

13510
来自专栏流浪猫的golang

go panic与recover分析及错误处理

error 是一种类型,表示错误状态的类型,如果没有错误则是nil。直白点将:error 类型就是描述错误的一种类型。

12730
来自专栏吴老师移动开发

[Flutter]请求阿里百川的API

简单封装了一下,请求阿里百川的api。只是做了一个简单的get请求封装,要更加优雅可以自己再封装一下。

43840
来自专栏散尽浮华

Python介绍

Python概述 Python创始人是吉多.范罗苏姆。在1989年万圣节期间为打发时间而开发的。 目前Python在TIOBE排行榜第五位置 ? Python可...

507100
来自专栏欧阳大哥的轮子

深入解构objc_msgSend函数的实现

熟悉OC语言的Runtime(运行时)机制以及对象方法调用机制的开发者都知道,所有OC方法调用在编译时都会转化为对C函数objc_msgSend的调用。

12120
来自专栏枕边书

PHP用mb_string函数库处理与windows相关中文字符

昨天想批处理以前下载的一堆文件,把文件里的关键内容用正则匹配出来,集中处理。在操作文件时遇到一个问题,就是windows操作系统中的编码问题。 我们都知道win...

233100

扫码关注云+社区

领取腾讯云代金券