一般在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>
....