• 写一个属于自己的模板引擎(3)


    接上(2)

    检测所有模版引擎的语句,发现错误和不对的就产生错误!
    成员变量:

    1. private $template//用来保存模版的内容
    2. private $IF_LINE_NUM//用来保存IF所在的行数
    3. private $ENDIF_LINE_NUM//用来保存ENDIF所在的行数
    4. private $FOREACH_LINE_NUM//用来保存FOREACH所在的行数
    5. private $ENDFOREACH_LINE_NUM//用来保存ENDFOREACH所在的行数
    6. private $ERRORS//用来保存错误信息


    构造函数:

    1. public function __construct($file_name NULL) {
    2.         if(isset($file_name) && trim($file_name) != '') {
    3.                 $this->set_file($file_name);
    4.         }
    5. }
    set_file()方法主要是用来打开模版文件和读取文件内容的:
    1. public function set_file($file_name) {
    2.         $file_name TPL_DIR.$file_name;
    3.         if(file_exists($file_name)) {
    4.                 $fp fopen($file_name'r') OR exit('错误:不能打开模板文件');
    5.                 if(($fs filesize($file_name)) > 0)
    6.                 $this->template fread($fp$fs);
    7.                 fclose($fp);
    8.                 return true;
    9.         }
    10.         exit('错误:模板文件不存在');
    11. }
    然后就是到最重要的start方法:
    1. function start($display FALSE) {
    2.         if(strpos($this->template'{#}') !== false) {
    3.                 if(!preg_match("/\{#\}[^({#})]*\{#\}/"$this->template)) {
    4.                         exit('错误:{#}没有关闭');
    5.                 }
    6.         }
    7.         $this->template explode("\n"$this->template);
    8.                 
    9.         $line_number 1;
    10.         foreach($this->template as $line) {
    11.                 if(trim($line) != '') {
    12.                         if(preg_match("/\{\s*if/"$line)) {
    13.                                 $this->IF_LINE_NUM[] = $line_number;
    14.                         }
    15.                         if(preg_match("/\{\s*\/if\s*\}/"$line)) {
    16.                                 $this->ENDIF_LINE_NUM[] = $line_number;
    17.                         }
    18.                         
    19.                                 if(preg_match("/\{\s*\\$[0-9a-zA-Z_]+\->foreach\(\s*[0-9a-zA-Z_]+\s*,\s*[0-9a-zA-Z_]+\s*\)\s*\}/"$line)) {
    20.                                 $this->FOREACH_LINE_NUM[] = $line_number;
    21.                         }
    22.                                 
    23.                         if(preg_match("/\{\s*\/foreach\s*\}/"$line)) {
    24.                                 $this->ENDFOREACH_LINE_NUM[] = $line_number;
    25.                         }
    26.                                 
    27.                         if(strpos($line"{include") !== false) {
    28.                                 if(!preg_match("/\{include \"[^}]*\"\}/"$line)) {
    29.                                         $this->ERRORS[] = '错误:INCLUDE语法使用错误,在行<font color="red">'.$line_number.'</font>';
    30.                                 }
    31.                         }
    32.                 }
    33.                 $line_number++;
    34.         }
    35.         $this->check_if();
    36.         $this->check_foreach();
    37.         if(count($this->ERRORS) > 0) {
    38.                 echo '<div style="border:1px solid #f60;padding:10px;500px;font-size:12px;color:#800;">';
    39.                 foreach($this->ERRORS as $e) {
    40.                         echo $e'<br/>';
    41.                 }
    42.                 echo '</div>';
    43.         } else {
    44.                 if($display)
    45.                         echo $this->highlight_html(implode('',$this->template));
    46.                 echo '<div style="border:1px solid #f60;padding:10px;200px;font-size:12px;text-align:center;color:#800;">恭喜:模版没有错误</div>';
    47.         }
    48. }

    这个方法有点复杂,所以我会一步步说明的:
    (1)
    1. if(strpos($this->template'{#}') !== false) {
    2.         if(!preg_match("/\{#\}[^({#})]*\{#\}/"$this->template)) {
    3.                 exit('错误:{#}没有关闭');
    4.         }
    5. }


    这个语句的用途是检测是否关闭了注释语句,如果没有关闭就强行退出检测!这个检测很简单,就是如果存在{#}但是不存在{#}……{#}就表示没有关闭注释语句。
    (2)
    1. $this->template explode("\n"$this->template);

    这个语句是用来把模版内容按换行来分割成数组。
    (3)
    1. $line_number 1;
    2.         foreach($this->template as $line) {
    这里是循环数组。
    (4)
    1. if(preg_match("/\{\s*if/"$line)) {
    2.         $this->IF_LINE_NUM[] = $line_number;
    3. }
    上面是匹配{if}语句的,并保存行数到IF_LINE_NUM变量中;
    1. if(preg_match("/\{\s*\/if\s*\}/"$line)) {
    2.         $this->ENDIF_LINE_NUM[] = $line_number;
    3. }

    上面是匹配{/if}的,并保存行数到ENDIF _LINE_NUM变量中;
    如此类推:
    1. if(preg_match("/\{\s*\\$[0-9a-zA-Z_]+\->foreach\(\s*[0-9a-zA-Z_]+\s*,\s*[0-9a-zA-Z_]+\s*\)\s*\}/"$line)) {
    2.         $this->FOREACH_LINE_NUM[] = $line_number;
    3. }                                
    4. if(preg_match("/\{\s*\/foreach\s*\}/"$line)) {
    5.         $this->ENDFOREACH_LINE_NUM[] = $line_number;
    6. }

    (5)
    1. if(strpos($line"{include") !== false) {
    2.         if(!preg_match("/\{include \"[^}]*\"\}/"$line)) {
    3.                 $this->ERRORS[] = '错误:INCLUDE语法使用错误,在行<font color="red">'.$line_number.'</font>';
    4.                 }
    5. }

    上面是检测include语法是否正确(是否符合{include “……”})。
    (6)
    1. $this->check_if();
    2. $this->check_foreach();

    调用上面的两个方法;这两个方法是用来检测if和foreach是否嵌套合理和是否关闭了。
    check_if()方法:
    1. private function check_if() {
    2.                 $ifs count($this->IF_LINE_NUM);
    3.                 for($i $i $ifs $i++) {
    4.                         if(isset($this->ENDIF_LINE_NUM[$i])) {
    5.                                 if($this->IF_LINE_NUM[$i] > $this->ENDIF_LINE_NUM[$i]) {
    6.                                         $this->ERRORS[] = '错误:在没有IF的情况下使用END IF,在行<font color="red">'.$this->ENDIF_LINE_NUM[$i].'</font>';
    7.                                 }
    8.                         } else {
    9.                                 $this->ERRORS[] = '错误:IF没有关闭,在行<font color="red">'.$this->IF_LINE_NUM[$i].'</font>';
    10.                         }
    11.                 }
    12.                 if(count($this->IF_LINE_NUM) == && count($this->ENDIF_LINE_NUM) > 0) {
    13.                         foreach($this->ENDIF_LINE_NUM as $line_number) {
    14.                                 $this->ERRORS[] = '错误:在没有IF的情况下使用END IF,在行<font color="red">'.$line_number.'</font>';
    15.                         }
    16.                 }
    17.         }

    从上面的代码可以看出,我们主要是根据IF和ENDIF的函数和数量来判断是否嵌套正确和关闭的!假如EndIF的行数位置比IF要高,就说明没有IF就使用ENDIF了!加入ENDIF和IF的数量不一样,就说明IF没有关闭!!
    Check_foreach()方法:
    1. private function check_foreach() {
    2.                 $foreachs count($this->FOREACH_LINE_NUM);
    3.                 for($i $i $foreachs $i++) {
    4.                         if(isset($this->ENDFOREACH_LINE_NUM[$i])) {
    5.                                 if($this->FOREACH_LINE_NUM[$i] > $this->ENDFOREACH_LINE_NUM[$i]) {
    6.                                         $this->ERRORS[] = '错误:在没有FOREACH的情况下使用END FOREACH,在行<font color="red">'.$this->ENDFOREACH_LINE_NUM[$i].'</font>';
    7.                                 }
    8.                         } else {
    9.                                 $this->ERRORS[] = '错误:FOREACH没有关闭,在行<font color="red">'.$this->FOREACH_LINE_NUM[$i].'</font>';
    10.                         }
    11.                 }
    12.                 if(count($this->FOREACH_LINE_NUM) == && count($this->ENDFOREACH_LINE_NUM) > 0) {
    13.                         foreach($this->ENDFOREACH_LINE_NUM as $line_number) {
    14.                                 $this->ERRORS[] = '错误:在没有FOREACH的情况下使用END FOREACH,在行<font color="red">'.$line_number.'</font>';
    15.                         }
    16.                 }
    17.         }

    Check_forech()方法的原来个check_if()方法一样!!

    (7)
    1. if(count($this->ERRORS) > 0) {
    2.                 echo '<div style="border:1px solid #f60;padding:10px;500px;font-size:12px;color:#800;">';
    3.                 foreach($this->ERRORS as $e) {
    4.                         echo $e'<br/>';
    5.                 }
    6.                 echo '</div>';
    7.         }
    这里是显示错误的!!
    最后就是highlight_html()方法:
    1. private function highlight_html($code)        {
    2.                 $code  str_replace('<''<'$code);
    3.                 $code  str_replace('>''>'$code);
    4.                 $code  =  preg_replace('/([a-zA-Z_]+)=/',  '<font color="#FF0000">$1=</font>',  $code);
    5.                 $code  =  preg_replace('/(<[\/a-zA-Z0-9&;]+)/',  '<font color="#0000FF">$1</font>',  $code);
    6.                 $code  =  str_replace('<!--',  '<font color="#008080"><!--',  $code);
    7.                 $code  =  str_replace('-->',  '--></font>',  $code);
    8.                 $code  =  preg_replace('/[\r\n]+/',  "\n",  $code);
    9.                 $code  nl2br($code);
    10.                 return $code;
    11.         }


    这个方法主要是用来高亮HTML标签的!!在上面那个start()方法中会使用的这个方法!
    至此,我们的模版引擎就完成了!

    Show show全相:
    1. <?php
    2. /**
    3. *
    4. * @author :PHP毛毛虫
    5. * @copyright :2008-12-24圣诞节
    6. *
    7. */
    8. class StupidDebuger {
    9.         private $template;
    10.         private $IF_LINE_NUM;
    11.         private $ENDIF_LINE_NUM;
    12.         private $FOREACH_LINE_NUM;
    13.         private $ENDFOREACH_LINE_NUM;
    14.         private $ERRORS;
    15.         
    16.         public function __construct($file_name NULL) {
    17.                 if(isset($file_name) && trim($file_name) != '') {
    18.                         $this->set_file($file_name);
    19.                 }
    20.         }
    21.         
    22.         public function set_file($file_name) {
    23.                 $file_name TPL_DIR.$file_name;
    24.                 if(file_exists($file_name)) {
    25.                         $fp fopen($file_name'r') OR exit('错误:不能打开模板文件');
    26.                         if(($fs filesize($file_name)) > 0)
    27.                         $this->template fread($fp$fs);
    28.                         fclose($fp);
    29.                         return true;
    30.                 }
    31.                 exit('错误:模板文件不存在');
    32.         }
    33.         
    34.         function start($display FALSE) {
    35.                 if(strpos($this->template'{#}') !== false) {
    36.                         if(!preg_match("/\{#\}[^({#})]*\{#\}/"$this->template)) {
    37.                                 exit('错误:{#}没有关闭');
    38.                         }
    39.                 }
    40.                 $this->template explode("\n"$this->template);
    41.                 
    42.                 $line_number 1;
    43.                 foreach($this->template as $line) {
    44.                         if(trim($line) != '') {
    45.                                 if(preg_match("/\{\s*if/"$line)) {
    46.                                         $this->IF_LINE_NUM[] = $line_number;
    47.                                 }
    48.                                 if(preg_match("/\{\s*\/if\s*\}/"$line)) {
    49.                                         $this->ENDIF_LINE_NUM[] = $line_number;
    50.                                 }
    51.                         
    52.                                 if(preg_match("/\{\s*\\$[0-9a-zA-Z_]+\->foreach\(\s*[0-9a-zA-Z_]+\s*,\s*[0-9a-zA-Z_]+\s*\)\s*\}/"$line)) {
    53.                                         $this->FOREACH_LINE_NUM[] = $line_number;
    54.                                 }
    55.                                 
    56.                                 if(preg_match("/\{\s*\/foreach\s*\}/"$line)) {
    57.                                         $this->ENDFOREACH_LINE_NUM[] = $line_number;
    58.                                 }
    59.                                 
    60.                                 if(strpos($line"{include") !== false) {
    61.                                         if(!preg_match("/\{include \"[^}]*\"\}/"$line)) {
    62.                                                 $this->ERRORS[] = '错误:INCLUDE语法使用错误,在行<font color="red">'.$line_number.'</font>';
    63.                                         }
    64.                                 }
    65.                         }
    66.                         $line_number++;
    67.                 }
    68.                 $this->check_if();
    69.                 $this->check_foreach();
    70.                 if(count($this->ERRORS) > 0) {
    71.                         echo '<div style="border:1px solid #f60;padding:10px;500px;font-size:12px;color:#800;">';
    72.                         foreach($this->ERRORS as $e) {
    73.                                 echo $e'<br/>';
    74.                         }
    75.                         echo '</div>';
    76.                 } else {
    77.                         if($display)
    78.                                 echo $this->highlight_html(implode('',$this->template));
    79.                         echo '<div style="border:1px solid #f60;padding:10px;200px;font-size:12px;text-align:center;color:#800;">恭喜:模版没有错误</div>';
    80.                 }
    81.         }
    82.         
    83.         private function check_if() {
    84.                 $ifs count($this->IF_LINE_NUM);
    85.                 for($i $i $ifs $i++) {
    86.                         if(isset($this->ENDIF_LINE_NUM[$i])) {
    87.                                 if($this->IF_LINE_NUM[$i] > $this->ENDIF_LINE_NUM[$i]) {
    88.                                         $this->ERRORS[] = '错误:在没有IF的情况下使用END IF,在行<font color="red">'.$this->ENDIF_LINE_NUM[$i].'</font>';
    89.                                 }
    90.                         } else {
    91.                                 $this->ERRORS[] = '错误:IF没有关闭,在行<font color="red">'.$this->IF_LINE_NUM[$i].'</font>';
    92.                         }
    93.                 }
    94.                 if(count($this->IF_LINE_NUM) == && count($this->ENDIF_LINE_NUM) > 0) {
    95.                         foreach($this->ENDIF_LINE_NUM as $line_number) {
    96.                                 $this->ERRORS[] = '错误:在没有IF的情况下使用END IF,在行<font color="red">'.$line_number.'</font>';
    97.                         }
    98.                 }
    99.         }
    100.         
    101.         private function check_foreach() {
    102.                 $foreachs count($this->FOREACH_LINE_NUM);
    103.                 for($i $i $foreachs $i++) {
    104.                         if(isset($this->ENDFOREACH_LINE_NUM[$i])) {
    105.                                 if($this->FOREACH_LINE_NUM[$i] > $this->ENDFOREACH_LINE_NUM[$i]) {
    106.                                         $this->ERRORS[] = '错误:在没有FOREACH的情况下使用END FOREACH,在行<font color="red">'.$this->ENDFOREACH_LINE_NUM[$i].'</font>';
    107.                                 }
    108.                         } else {
    109.                                 $this->ERRORS[] = '错误:FOREACH没有关闭,在行<font color="red">'.$this->FOREACH_LINE_NUM[$i].'</font>';
    110.                         }
    111.                 }
    112.                 if(count($this->FOREACH_LINE_NUM) == && count($this->ENDFOREACH_LINE_NUM) > 0) {
    113.                         foreach($this->ENDFOREACH_LINE_NUM as $line_number) {
    114.                                 $this->ERRORS[] = '错误:在没有FOREACH的情况下使用END FOREACH,在行<font color="red">'.$line_number.'</font>';
    115.                         }
    116.                 }
    117.         }
    118.         
    119.         private function highlight_html($code)        {
    120.                 $code  str_replace('<''<'$code);
    121.                 $code  str_replace('>''>'$code);
    122.                 $code  =  preg_replace('/([a-zA-Z_]+)=/',  '<font color="#FF0000">$1=</font>',  $code);
    123.                 $code  =  preg_replace('/(<[\/a-zA-Z0-9&;]+)/',  '<font color="#0000FF">$1</font>',  $code);
    124.                 $code  =  str_replace('<!--',  '<font color="#008080"><!--',  $code);
    125.                 $code  =  str_replace('-->',  '--></font>',  $code);
    126.                 $code  =  preg_replace('/[\r\n]+/',  "\n",  $code);
    127.                 $code  nl2br($code);
    128.                 return $code;
    129.         }
    130. }
  • 相关阅读:
    windwos8.1英文版安装SQL2008 R2中断停止的解决方案
    indwows8.1 英文版64位安装数据库时出现The ENU localization is not supported by this SQL Server media
    Server Tomcat v7.0 Server at localhost was unable to start within 45 seconds
    SQL数据附加问题
    eclipse,myeclipse中集合svn的方法
    JAVA SSH 框架介绍
    SSH框架-相关知识点
    SuperMapRealSpace Heading Tilt Roll的理解
    SuperMap iserver manage不能访问本地目的(IE9)
    Myeclipse中js文件中的乱码处理
  • 原文地址:https://www.cnblogs.com/kuyuecs/p/1390633.html
Copyright © 2020-2023  润新知