军用网站建设,网站建设应注意的问题,网站建设实训的报告,最新网站建设的模板下载今天讲的是dedecms最关键的东西#xff0c;模板分析啦。也就是dedetag.class.php 里面的ParseTemplet方法 模板解析方法 先看看一个dedecms标签,大家心里有个数#xff1a; {dede:arclist row10 orderbypubdate typeimage. imgwidth143 imgheight106} lia href模板分析啦。也就是dedetag.class.php 里面的ParseTemplet方法 模板解析方法 先看看一个dedecms标签,大家心里有个数 {dede:arclist row10 orderbypubdate typeimage. imgwidth143 imgheight106} lia href[field:arcurl/][field:image/]span classtitle[field:title/]/span/a/li {/dede:arclist} 参考上面标签我们就可以进一步分析啦。 这里假定你已经了解了dedecms的标签形式标签格式和标签种类。 下面我们展开分析 先看方法前面初始化一些最基本的变量 1标签起始符号和结束符号。如“{”和} $TagStartWord $this-TagStartWord; $TagEndWord $this-TagEndWord; 2设置临时变量用于临时存储查找到的新标签在模板中的起始位置和结束位置。 $sPos 0; $ePos 0; 3设定完整标签起始字符串和结束字符串。比如“{dede:”这种形式 $FullTagStartWord $TagStartWord.$this-NameSpace.:; $sTagEndWord $TagStartWord./.$this-NameSpace.:; $eTagEndWord /.$TagEndWord; 这里值得注意的是结束部分分两种一种是类似于{aa:ff /}单体结构标签一种是类似于{aa:fff}{/aa:fff}符合结构标签 4获取标签其实字符串{dede:长度和整个模板的长度 $tsLen strlen($FullTagStartWord); $sourceLenstrlen($this-SourceString); 上面就是初始变量设置部分啦。 接下来是个小判断如果整个模板的长度不大于标签起始字符串的长度加3就退出。 if( $sourceLen ($tsLen 3) ){ return; } 为什么要加3也就是模板长度最少应该是标签起始字符串长度加4呢 我们看看我们能写出的最短标签 {dede:a/} 冒号后面是可能出现的最短字符串就是3个所以这里如果小于3就连最起码的一个标签都无法完整所以要做这个判断至于等于嘛我个人认为是没必要的。 好继续往下看下面两句 $cAtt new DedeAttributeParse(); $cAtt-charToLow $this-CharToLow; 创建了一个DedeAttributeParse类并设定了CharToLow属性这个类看名字应该是标签属性分析类charToLow就是是否把字符串自动转化为小写。 接下来就是一个长长的for循环了遍历模板字符串的每个字符进行分析提取模板中的标签。 for($i0; $i $sourceLen; $i) 下面我们就来看看这个for循环里面是怎么分析的吧 先定义一个临时变量存储当前找到的标签的名字 $tTagName ; 下面是一个判断注释写得很清楚但我们现在还看不懂所以先知道有这么个判断就行啦 //如果不进行此判断将无法识别相连的两个标记 if($i-1 0){ $ss $i-1; }else{ $ss 0; } 设定了一个变量$ss后面留意一下就是了。 下面就是查找标签了 $sPos strpos($this-SourceString,$FullTagStartWord,$ss); $isTag $sPos; 找到在模板字符串中从$ss指定的位置开始第一个类似“{dede:”这种标签头的位置并把$isTag变量设置为strpos的返回值这是个偷懒的写法应该明确指出查到标签了就是true而不是任意字符。 我们看到这里用到了$ss作用是设定查找的起始位置。 我们继续往下看吧 下面一个if语句好像是对第一个字符开始就是标签的情况下的一种补充 搞不懂了本来就能找到的加这句什么意思呢多余哦这个肯定有更好方法的。不多说这句了。 在下来的if就是如果没找到标签就不循环了不解释。 再下来一个子循环 for($j($sPos$tsLen);$j($sPos$tsLen$this-TagMaxLen);$j) $tsLen我们之前说了是标签头类似{dede:长度 那这个for的解释就是遍历从标签头的下一个字符开始到标签最大长度位置结束这中间的所有字符看来是要找标签名字啦 再看看for循环里面很简单的几句就是找出标签的名字如何找出来的呢 if($j($sourceLen-1)){break;}else if( ereg([/ \t\r\n],$this-SourceString[$j]) || $this-SourceString[$j] $this-TagEndWord ){break;}else{$tTagName . $this-SourceString[$j];} 这个for里面的if语句两种情况下名字结束一种是字符位置到模板的字后一个位置另一种是发现了空格、断行、tab符、/等或找到了标签结束符如} 通过这个for循环标签的名字就弄出来了保存在变量$tTagName中。 下面是一个极其长的if语句啦判断$tTagName变量是否为空如果是空则跳出循环标签出错了嘛不过跳出前还设置$i有什么用看不懂。 接下来重点就是找到标签名字的情况啦。 先是设置几个变量 $i $sPos$tsLen; $endPos -1; $fullTagEndWordThis $sTagEndWord.$tTagName.$TagEndWord; 把循环模板字符串的指针$i跳到标签名字开始的地方。然后设置变量$endPos 为-1组合出一种标签结束符{/dede:xxx} 接下来是查找三个位置$eTagEndWord/}、$FullTagStartWord{dede:、$fullTagEndWordThis{/dede:xxx} $e1 strpos($this-SourceString,$eTagEndWord, $i); $e2 strpos($this-SourceString,$FullTagStartWord, $i); $e3 strpos($this-SourceString,$fullTagEndWordThis,$i); $e1就是在标签名字找到后第一个/}出现的位置$e2就是第一个“{dede:”出现的位置$e3就是第一个{/dede:xxx}出现的位置。这里注意获取$e3值的时候$fullTagEndWordThis是以当前找到的标签为名字的结束字符串。 在下面几句是统一$e1 $e2 $e3的值使这三个变量如果找到要找的标签字符串就保存位置找不到就保存-1 $e1 trim($e1); $e2 trim($e2); $e3 trim($e3); $e1 ($e1 ? -1 : $e1); $e2 ($e2 ? -1 : $e2); $e3 ($e3 ? -1 : $e3); 接下来就要根据这三个值进行一些处理啦。处理什么呢我们先看看这段代码吧 //not found {/tag:if($e3-1) {$endPos $e1;$elen $endPos strlen($eTagEndWord);}//not found /}else if($e1-1) {$endPos $e3;$elen $endPos strlen($fullTagEndWordThis);}//found /} and found {/dede:else{//if /} more near {dede:、{/dede: , end tag is /}, else is {/dede:if($e1 $e2 $e1 $e3 ){$endPos $e1;$elen $endPos strlen($eTagEndWord);}else{$endPos $e3;$elen $endPos strlen($fullTagEndWordThis);}} 我们知道dedecms标签结束有两种方式一种是/}这种方式还有一种是{/dede:xxx}除此之外没有他选如果没有这两种结束只能说明一个问题模板内的标签不完整。这个if语句做了一个假设就是两种标签结束方式一定是有一种存在的。 if的第一个分支假设$e3为-1也就是/}这种方式存在所以设置了标签结束符位置变量$endPos为变量$e1的值而此时标签最终结束位置就知道了是$endPos加上/}的长度。 if语句的第二个分支和第一个类似只是假定找到了{/dede:xxx}。 if语句的else部分是假定两个都找到了有这种可能吗?那么就要进一步分析啦如果/}这种结束符出现的位置比下个标签起始位置靠前而且还比$e3的结束符{/dede:xxx}位置靠前说明当前找到的/}就是当前标签的结束符否则一定是{/dede:xxx}这种啦。 上面通过$e1 $e2 $e3的变量设置和一个if语句最终是要得到两个变量$endPos和$elen当前标签结束符开始的位置和结束位置。 下面又是一个if语句很简单通过endPos是否为-1判断当前标签是否正确结束。如果没有正确结束则打印一段文字然后就退出循环。这块设计的是否可以再好点呢比如把这块出错的标签替换为一个错误信息或在做模板分析前统一检查语法正确性以保证更快速分析模板。 再继续往下看又是设置了两个变量。 $i $elen; $ePos $endPos; 由于找到当前循环要找的标签所以设置主循环for的循环变量$i到下个标签的起始位置。 设置当前标签的结束符起始位置$ePos。 当前标签的开始位置和结束位置都确定了接下来就可以分析标签的属性了我们继续。 $attStr ; $innerText ; $startInner 0; 三个变量我们了解到标签内部有两种东西一种是属性字符串还有一种是内容字符串。$startInner 变量指示内容字符串是否开始奇怪为什么不用布尔值呢。 下面一个for循环开始提取这些字符串从标签名称后面到结束符开始之前的部分。 for($j($sPos$tsLen);$j $ePos;$j) 看看循环里面是怎么提取属性字符串和内容字符串的。 if($startInner0 ($this-SourceString[$j]$TagEndWord $this-SourceString[$j-1]!\\) ){$startInner1;continue;}if($startInner0){$attStr . $this-SourceString[$j];}else{$innerText . $this-SourceString[$j];} 嗯用了两个if语句第一个语句是用来判断内容字符串是否开始的。第二个if语句根据内容字符串开始指示符判断分别读取内容字符串和属性字符串。 个人认为通过特殊标识符截字更快一些。 这里面还有个问题就是是否内容字符串开始是如何判断的呢 我们看看第一个if if($startInner0 ($this-SourceString[$j]$TagEndWord $this-SourceString[$j-1]!\\) ) $startInner0这句就是做个过滤当读取内容字符串的时候就不会再走这个if了关键是后面括号里面的内容。 如果当前字符为标签结束符$TagEndWord}而且结束符的前一个字符不是反斜杠的时候就是属性部分结束了如果是反斜杠说明是一些模板内容之类的了。 通过上面的for循环我们就提取出了当前标签的属性和内容接下来就开始分析属性和内容啦 $cAtt-SetSource($attStr);if($cAtt-cAttributes-GetTagName()!){$this-Count;$CDTag new DedeTag();$CDTag-TagName $cAtt-cAttributes-GetTagName();$CDTag-StartPos $sPos;$CDTag-EndPos $i;$CDTag-CAttribute $cAtt-cAttributes;$CDTag-IsReplace FALSE;$CDTag-TagID $this-Count;$CDTag-InnerText $innerText;$this-CTags[$this-Count] $CDTag;} 通过属性分析类来进行分析啦然后创建DedeTag标签类实例就是创建一个标签对象然后把当前标签的属性都放进这个标签对象。 包括标签名称、起始位置、结束位置、属性数组、内部字符串等。 然后把这个新的标签对象放到DedeTagParse类的CTags数组中。 这样一个标签就分析完了也结束了一次最外层的for循环。原来每循环一次只能分析出一个标签有多少个标签就 有可能循环多少次。 整个模板分析结束后如果允许缓存再调用SaveCache方法把当前模板的标签信息保存到缓存文件或者叫中间信息文件。 ps其实整个模板解析方法也只是把模板标签的信息记录了下来放到新建的dedetag对象中然后保存到当前DedeParse类的CTags数组中类似于上一节我们从缓存文件分析的过程 分析到这里大家可能有个疑问 织梦系统是怎么通过标签获取到数据的呢这就是我们下部分需要分析的其实细心的朋友应该已经知道肯定是我们之前在视图类里面的MakeOneTag这个方法里面 模板分析就讲完啦这样该有的信息就都有了我们又可以回到LoadTemplate方法继续啦。 阚荣华博客www.kanronghua.com 欢迎学习和交流转载于:https://www.cnblogs.com/ronghua/p/5936084.html