Thinkphp修改一句代碼,使得foreach標籤支持對象,增長變量[數組對象]混合解析法!

今天修補一個老項目中,使用的是TP框架,到視圖區發現對象沒法遍歷輸出。真夠鬱悶的,對於不喜歡數組喜歡變量的強迫症來講就得琢磨琢磨。搞了半天,搜了半天沒找到滿意的結果。以後順道去了下官網的手冊看了看,寥寥幾行說明,真是醉了。php

開啓自行調試研究模式。

TP默認視圖循環代碼編程

<foreach name="apidatas" item="val">
{$val.sta_name} //這是默認輸出數組的方式 
</foreach>

打開他生成後的緩存文件,裏面對應生成的代碼。(Rumtime/Cache/*****.php)api

<?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對象的指向符是 ->  因爲右側是「>」符號會跟其餘標籤衝突,也就致使了不少人都常常報的一個ui

XML標籤語法錯誤this

研究後發現只須要更改視圖頁對象變量的引用方式便可 由 "->" 換到 ":"spa

此處是在內置的尖括號<>標籤內使用 : 代替->  如果在 大括號{} 標籤內也可以使用->

<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;
    }

以上修改後方法只支持先數組後對象方式,想要更奇葩的能夠本身研究後發出來哦!

相關文章
相關標籤/搜索