一般在mvc框架或者过程式代码中,数据的调取和模版的渲染分别由c层( control,控制器层 )和v层( view, 视图层 )来完成.

  这样要分别在c和v中分别写代码,还是比较麻烦的。现在php的内容管理系统通常都比较流行使用<get xxx>标签或者模版标签,例如phpcms和dedecms,  所以自己也给美工写了个 parse_get() 小解释器。

 

只需要在html模版中写入下面一段内容, 就得出数据和样式.

 


   <!-- 取得 分类001 的5条数据 -->
    <ul class="art_ul" >

    <?php
     $get01 = '
      <get
       fields="aid , title ,content , addtime"
       condition="sid=\'001\'" 
       order="aid DESC" 
       limit="0,5" 
       
       L_tag="<li>"
       L_class="h3"
       L_loop_class="pretty_1|pretty_2|pretty_3"
      >
       <span class="title">
        <a href="?ac=show&id=$aid" title="$title" target="_blank" >$title</a></span>
       <span class="pushdate" title="">$addtime</span>
      </get>
     ';
     echo parse_get( $get01 );
    ?>

    </ul>

 

再加上pretty css

<style type="text/css">
	.pretty_1 { background-color: #FFE4CA; }
	.pretty_2 { background-color: #E6E6FF; }
	.pretty_3 { background-color: #83B3CF; }
	.pretty_3 { background-color: #E1D671; }
</style>

 



显示结果::

 

php实现代码

  1 <?php
  2 /*
  3 * 功能: 解释一条<get>标签, 返回请求的数据
  4 * 参数: @string: $get_str , get标签字符串; @array: $data , 若要直接解释/使用此数组的数据则请填写.
  5 * 返回: html代码
  6 
  7 * @author: 王奇疏
  8 */
  9 function parse_get( $get_str , $data=array() ){
 10 
 11     // 按 > 号切成2部分
 12     $t = preg_split( '@\B>\B@' , $get_str , 2 ); 
 13     empty( $t ) && exit( 'get标签语法不正确.' ); 
 14     if ( count( $t ) > 1 ){
 15         list( $head , $entity ) = $t;
 16         $entity = explode( '</get>' , $entity , 2 );
 17         $entity = $entity[0];
 18     }
 19     else{
 20         $head = $t;
 21         $entity = '';
 22     }
 23 
 24     // 判断数据来源类型
 25     $patten = '<get\s+(db|fields|condition|limit|order|sql|src|require)\s*=';
 26     !preg_match( "@{$patten}@i" , $head , $type ) && exit( 'get标签出错了:您填写的数据来源不能被识别.' );
 27     if ( !isset( $type[1] ) && empty( $type[1] ) ) return false;
 28     $type = $type[1];
 29     // 以下字段判断为db类型
 30     false !== stripos( 'db|fields|condition|limit|order' , $type ) && $type = 'db';
 31 
 32     // 提取head部分内的字段
 33     $patten = '([a-z0-9_\-]+)\s*=\s*([\'\"])?(.+)\\2\s';
 34     preg_match_all( "@{$patten}@i" , $head , $res );
 35     if ( empty( $res ) ) return false;
 36     $fields = array(  );
 37     foreach ( $res[1] as $n=>$k ){
 38         $k = strtolower( $k );
 39         $fields[$k] = $res[3][$n];
 40     }
 41     
 42     // 根据各类型数据源取得数据
 43     $sql = '';
 44 
 45     // 使用输入的参数$data的数据 
 46     if ( !empty( $data ) ){
 47 
 48     }
 49     // 按db字段构造sql语句
 50     elseif ( 'db' == $type ){
 51         $sql = 'SELECT ';
 52         
 53         // select 字段
 54         $set = '*';
 55         isset( $fields['fields'] ) && $set = trim( $fields['fields'] ); 
 56         $sql .= " {$set} ";
 57         // 表名
 58         $set = 'FROM article'; 
 59         if ( isset( $fields['db_table'] ) ){
 60             $set = trim( $fields['db_table'] ); 
 61             false === stripos( $set , 'from' ) && $set = 'FROM '.$set;
 62         }
 63         $sql .= " {$set} ";
 64         // 条件
 65         if ( isset( $fields['condition'] ) ){
 66             $set = $fields['condition'];
 67             if ( false !== strpos( $set , '=' ) ){
 68                 $set = explode( '=' , $set , 2 );
 69                 $set = $set[0].'='.stripslashes( $set[1] );
 70             }
 71             false === stripos( $set , 'where' ) && $set = ' WHERE '.$set;
 72             $sql .= " {$set} ";
 73         }
 74         // 排序
 75         if ( isset( $fields['order'] ) ){
 76             $set = $fields['order'];
 77             false === stripos( $set , 'order' ) && $set = ' ORDER BY '.$set;
 78             $sql .= " {$set} ";
 79         }
 80         // limit限制
 81         if ( isset( $fields['limit'] ) ){
 82             $set = $fields['limit'];
 83             false === stripos( $set , 'limit' ) && $set = ' LIMIT '.$set;
 84             $sql .= " {$set} ";
 85         }
 86     
 87     }
 88     // 按sql语句
 89     elseif ( 'sql' == $type ){
 90         $sql = $fields['sql'];
 91     }
 92     // 按行取出文件数据
 93     elseif ( 'src' == $type ){
 94         $link = trim( $fields['src'] );
 95         $data = file_get_contents( $link );
 96         if ( isset( $fields['src_split'] ) ){
 97             $data = explode( $fields['src_split']  , $data );
 98             isset( $fields['number'] ) && $data = array_slice( $data , 0 , (int)$fields['number'] );
 99         }
100     }
101     // 载入文件数组
102     elseif ( 'require' == $type ){
103         $fname = basename( $fields['require'] );
104         !is_file( $fields['require'] ) && exit( 'get标签出错了: 您要载入数据的文件 '.$fname.' 不存在.' );
105         $data = require $fields['require'];
106         !is_array( $data ) && exit( 'get标签出错了: 您载入数据的文件 '.$fname.' 不是一个数组, 不能被使用.' ); 
107     }
108     else{
109         exit( 'get标签出错了: 您填写的数据来源不能被识别. ' ); 
110     }
111     
112     // 如果是mysql , 取出mysql数据
113     if ( !empty( $sql ) ){
114         // 执行请求
115         if ( isset( $fields['db_name'] ) ){
116             $db_name = $fields['db_name'];
117             $res = db::query( $sql , $db_name , false ); // 连接选定的数据库(数据库名称)
118         }
119         else{
120             $res = db::query( $sql );
121         }
122         // 取回结果
123         $data = array(  );
124         $i = 0;
125         $max = isset( $fields['number'] ) ? (int)$fields['number'] : 0; // 取多少条
126         while ( $row = db::fetch( $res ) ){
127             $data[] = $row;
128             ++$i;
129             if ( 0 != $max && $i >= $max ){
130                 break;
131             }
132         }
133     }    
134 
135 
136 
137     // 行标签开始和关闭
138     if ( isset( $fields['l_tag'] ) ){
139         $ltag = trim( $fields['l_tag'] , '<> ' ); // 行标签开始
140         $lclass = isset( $fields['l_class'] ) ? trim( $fields['l_class'] ) : ''; // 统一css类
141     }
142     else{
143         $ltag = $lclass = '' ;
144     }
145     // 行css类
146     $l_loop_class = array(); 
147     $l_loop_total = 0; // css类数
148     if ( isset( $fields['l_loop_class'] ) ){
149         $l_loop_class = trim( $fields['l_loop_class'] );
150         $l_loop_class = explode( '|' , $l_loop_class );
151         $l_loop_total = count( $l_loop_class );
152     }
153 
154     // 块标签开始和关闭
155     if ( isset( $fields['b_tag'] ) ){
156         $btag = trim( $fields['b_tag'] , '<> ' ); // 行标签开始
157         $bclass = isset( $fields['b_class'] ) ? trim( $fields['b_class'] ) : ''; // 统一css类
158     }
159     else{
160         $btag = $bclass = '' ;
161     }
162     // 块css类
163     $b_loop_class = array(); 
164     $b_loop_total = 0; // css类数
165     if ( isset( $fields['b_loop_class'] ) ){
166         $b_loop_class = trim( $fields['b_loop_class'] );
167         $b_loop_class = explode( '|' , $b_loop_class );
168         $b_loop_total = count( $b_loop_class );
169     }
170 
171 
172     // 取出entity 里面的变量, 用于替换
173     $entity_vars = false;
174     if ( !empty( $entity ) ){
175         preg_match_all( '@\$[a-zA-Z_][a-zA-Z0-9_\-]*@' , $entity , $entity_vars );
176         $entity_vars = !empty( $entity_vars[0] ) ? array_unique( $entity_vars[0] ) : false;
177     }
178 
179     /* 将数据按条件生成html代码 */
180     $html = '';
181     if ( !empty( $ltag ) ){
182         $i = 0;
183         foreach ( $data as $n=>$line ){
184             
185             // 替换实体中的变量为实体内容
186             $entity_str = '';
187             if ( false !== $entity_vars ){
188                 $rp = array();
189                 foreach ( $entity_vars as $var ){
190                     $var = ltrim( $var , '$' );
191                     $rp[] = $line[$var];
192                 }
193                 $entity_str = str_replace( $entity_vars , $rp , $entity ); // 变量名替换为字符
194             }
195 
196             $j = $i % $l_loop_total; // 循环css数
197             // css类样式汇总
198             $css_class = !empty( $lclass ) ? " class=\"{$lclass} {$l_loop_class[ $j ]}\" " : " class=\"{$l_loop_class[ $j ]}\" " ;
199             $line = "<{$ltag}{$css_class}>{$entity_str}</{$ltag}>\n";
200             $html .= $line;
201             ++$i;
202         }
203     }
204     else{
205         foreach ( $data as $n=>$line ){
206             // 替换实体中的变量为实体内容
207             $entity_str = '';
208             if ( false !== $entity_vars ){
209                 $rp = array();
210                 foreach ( $entity_vars as $var ){
211                     $var = ltrim( $var , '$' );
212                     $rp[] = $line[$var];
213                 }
214                 $entity_str = str_replace( $entity_vars , $rp , $entity ); // 变量名替换为字符
215             }
216             $line = "{$entity_str}\n";
217             $html .= $line;
218         }    
219     }
220 
221     return $html;
222 }

 




 说明::

// 数据解析器.  支持调用db字段,直接写sql,取文件,直接传入数组数据这4种方式的数据。
<get  ...>

// 获得数据
L是line的简写 , 表示1条数据;
B是block的简写 , 由setline条数据构成一个块.

|--------------------------------- |
|  |---------------------------|   |
|  |---------------------------|   |
|                                          |
|  |---------------------------|   |
|  |---------------------------|   |
|       ... ... ...                        |
|--------------------------------- | ( Block , line )

<get
 db_name="my_test_db" ( 数据库名称, 可省略。进入其它数据库调用数据时才填写 )
 db_table="article"   ( 表名, 可省略 )
 fields=""     ( 表内的字段 )
 condition=""    ( 条件 ) 
 limit=""      ( 限制 ) 

 sql = ""      ( 通过sql语句提取数据 )

 require = "data_array.php" ( 通过php文件载入一个数组 )
 
 src = "data.txt"   ( 引入其它数据来源, 例如txt文本或像引入外部js文件那样. )
 src_split = "\n\r"   ( 自定义对数据源的切分标记 , 分成多条数据. 默认用\n换行符切分数据源, 1行1条数据.  )
 
 number="10"    ( 取多少条数据 )

 L_tag = "<span>"  ( 【每条数据嵌套什么htm标签 )
 L_loop_class = ""  ( 对【每条】数据迭代使用什么css类 )
 L_class = ''    ( 表示对L_tag使用统一的、同一种css类 )

 L_top_click_attr=""  ( 置顶点击属性 )
 L_top_comment_attr="" ( 置顶推荐属性 )

 B_setline="3line"  ( 设多少条数据合为一个block【块】. 3line表示3条数据合为一个【块】  )
 B_tag="<div>"   ( 给一个【块】, 嵌套什么htm标签 )
 B_loop_class ='petty1|p2|p3'  ( 对【每个块】按次序重复(迭代)使用css属性, 用|分隔.将循环重复使用. )

 B_class = 'c1|c2|c3' ( 跟L_class作用相同. 表示对B_tag使用统一的、同一种css类)
>

 


举例1: 从data.txt中得到10条数据 , 1行1条数据. 给每条数据套用li标签 , 设置他们的属性是 li_1、li_2这样重复使用:
  
 <style type="text/css">.li_1 { font-weight:bold;} .li_2 { font-weight:nomal; } </style> <!-- 非常建议您css统一写到单独文件, 这里只是举例.  -->

 <ul>
  <get src='data.txt'  number='10' L_tag='li' L_loop_class='li_1|li_2'  >
 </ul>


举例2:
 从数据库article表得到10条文章, 栏目名是[本地新闻];
 给每条数据套用li标签;
 设每3条为一个块 , 每2个块一个样式(取决于B_loop_class有多少个值) .

 <ul>
  <get
   article classname='本地新闻' number='10'   // article表, 字段是classname=本地新闻 , 10条

   L_tag='li'  L_class='class'  L_loop_class='li_1|li_2'  // 每条数据用li标签包起来, 隔行使用不同的css类.

   B_tag='<dl>'  B_setline='3'  B_class='class'  B_loop_class='pretty1|pretty2'  // 每3行用dl包起来.  dl的属性
  >
 </ul>


举例3:
 从article(文章)表和comment(评论)表获得10条数据,
 每条显示标题 , 作者, 时间 , 评论数 .

 // 数据显示有顺序, 先写的先显示.
 <ul>
  <li style="color:red;"> 
  <get src='addtion_tips.php'  // 顶部显示一个提示. >
  </li>

  <get
   
   // mysql数据
   table='article AS at|comment AS cm'  // 等同于sql:  SELECT  article AS at,  comment AS cm
   table_attr=' at.id , at.title , at.author , at.pushtime , count( cm.id ) as cm_num '  // 选取哪些属性
   condition='at.classid=cm.classid AND classid=20  LIMIT 0,10 ' // 等同于sql语句的条件: where  at.classid=cm.classid AND classid=20
   
   // 控制样式
   L_class='class'  L_loop_class='li_1|li_2'  // 每条数据用li标签包起来, 隔行使用不同的css类.
   ....

  >
 
 </ul>
....
 

posted on 2012-10-23 01:04  王奇疏  阅读(270)  评论(0编辑  收藏  举报