PHP中MVC模式的模板引擎开发经验分享
程序员文章站
2024-02-04 21:56:22
使web系统的开发与维护更加方便,从而有效的节省人力物力,受到了越来越多企业的青眯。 模板引擎是mvc模式建立过程的重要方法,开发者可以设计一套赋予含义的标签,通过技术解析...
使web系统的开发与维护更加方便,从而有效的节省人力物力,受到了越来越多企业的青眯。
模板引擎是mvc模式建立过程的重要方法,开发者可以设计一套赋予含义的标签,通过技术解析处理有效的把数据逻辑处理从界面模板中提取出来,通过解读标签的含义把控制权提交给相应业务逻辑处理程序,从而获取到需要的数据,以模板设计的形式展现出来,使设计人员能把精力更多放在表现形式上。下面是我对模板引擎的认识与设计方法:
说的好听些叫模板引擎,实际就是解读模板数据的过程(个人观点^^)。通过我对建站方面的思考认识,网站在展现形式上无非归纳为单条和多条两种形式,那么我们可以设定两种对应标签(如data、list)来处理这两种情况,关键点在于解决两种标签的多层相互嵌套问题,基本适合实现80%界面形式。
解读模板的方法有多种,常用的包括字符串处理(解决嵌套稍麻烦)、正则表达式。在这里我选用的正则表达式,下面是我的处理方法(本文仅提供思路和参考代码,可能不能直接使用)。
模板文件解析类:
<?php
/*
* class: 模板解析类
* author: 51js.com-zmm
* date: 2011.3.1
* email: 304924248@qq.com
* blog: http://www.cnblogs.com/cnzmm/
*/
class template {
public $html, $vars, $btag, $etag;
public $bflag='{', $eflag='}', $pfix='zmm:';
private $folder, $file;
function __construct($vars=array()) {
!empty($vars) && $this->vars = $vars;
!empty($globals['cfg_tag_prefix']) &&
$this->pfix = $globals['cfg_tag_prefix'].':';
$this->btag = $this->bflag.$this->pfix;
$this->etag = $this->bflag.'\/'.$this->pfix;
empty(tags::$vars) && tags::$vars = &$this->vars;
}
public function loadtpl($tpl) {
$this->file = $this->gettplpath($tpl);
tags::$file = &$this->file;
if (is_file($this->file)) {
if ($this->gettplhtml()) {
$this->settpltags();
} else {
exit('模板文件加载失败!');
}
} else {
exit('模板文件['.$this->file.']不存在!');
}
}
private function gettplpath($tpl) {
$this->folder = website_dirroot.
$globals['cfg_tpl_root'];
return $this->folder.'/'.$tpl;
}
private function gettplhtml() {
$html = self::fmttplhtml(file_get_contents($this->file));
if (!empty($html)) {
$callfunc = tags::$prefix.'syntax';
$this->html = tags::$callfunc($html, new template());
} else {
exit('模板文件内容为空!');
} return true;
}
static public function fmttplhtml($html) {
return preg_replace('/(\r)|(\n)|(\t)|(\s{2,})/is', '', $html);
}
public function register($vars=array()) {
if (is_array($vars)) {
$this->vars = $vars;
tags::$vars = &$this->vars;
}
}
public function display($bool=false, $name="", $time=0) {
if (!empty($this->html)) {
if ($bool && !empty($name)) {
if (!is_int($time)) $time = 600;
$cache = new cache($time);
$cache->set($name, $this->html);
}
echo $this->html; flush();
} else {
exit('模板文件内容为空!');
}
}
public function setassign($souc, $info) {
if (!empty($this->html)) {
$this->html = str_ireplace($souc, self::fmttplhtml($info), $this->html);
} else {
exit('模板文件内容为空!');
}
}
private function settpltags() {
$this->setpaneltags(); $this->settrunktags(); $this->reghatchvars();
}
private function setpaneltags() {
$rule = $this->btag.'([^'.$this->eflag.']+)\/'.$this->eflag;
preg_match_all('/'.$rule.'/ism', $this->html, $out_matches);
$this->transtag($out_matches, 'panel'); unset($out_matches);
}
private function settrunktags() {
$rule = $this->btag.'(\w+)\s*([^'.$this->eflag.']*?)'.$this->eflag.
'((?:(?!'.$this->btag.')[\s\s]*?|(?r))*)'.$this->etag.'\\1\s*'.$this->eflag;
preg_match_all('/'.$rule.'/ism', $this->html, $out_matches);
$this->transtag($out_matches, 'trunk'); unset($out_matches);
}
private function transtag($result, $type) {
if (!empty($result[0])) {
switch ($type) {
case 'panel' : {
for ($i = 0; $i < count($result[0]); $i ++) {
$strtag = explode(' ', $result[1][$i], 2);
if (strpos($strtag[0], '.')) {
$itemarg = explode('.', $result[1][$i], 2);
$callfunc = tags::$prefix.ucfirst($itemarg[0]);
if (method_exists('tags', $callfunc)) {
$html = tags::$callfunc(chop($itemarg[1]));
if ($html !== false) {
$this->html = str_ireplace($result[0][$i], $html, $this->html);
}
}
} else {
$rule = '^([^\s]+)\s*([\s\s]+)$';
preg_match_all('/'.$rule.'/is', trim($result[1][$i]), $tmp_matches);
$callfunc = tags::$prefix.ucfirst($tmp_matches[1][0]);
if (method_exists('tags', $callfunc)) {
$html = tags::$callfunc($tmp_matches[2][0]);
if ($html !== false) {
$this->html = str_ireplace($result[0][$i], $html, $this->html);
}
} unset($tmp_matches);
}
} break;
}
case 'trunk' : {
for ($i = 0; $i < count($result[0]); $i ++) {
$callfunc = tags::$prefix.ucfirst($result[1][$i]);
if (method_exists('tags', $callfunc)) {
$html = tags::$callfunc($result[2][$i], $result[3][$i]);
$this->html = str_ireplace($result[0][$i], $html, $this->html);
}
} break;
}
default: break;
}
} else {
return false;
}
}
private function reghatchvars() {
$this->setpaneltags();
}
function __destruct() {}
}
?>
标签解析类:(目前暂时提供data、list两种标签的解析,说明思路)
<?php
/*
* class: 标签解析类
* author: 51js.com-zmm
* date: 2011.3.2
* email: 304924248@qq.com
* blog: http://www.cnblogs.com/cnzmm/
*/
class tags {
static private $attrs=null;
static public $file, $vars, $rule, $prefix='tag_';
static public function tag_syntax($html, $that) {
$rule = $that->btag.'if\s+([^'.$that->eflag.']+)\s*'.$that->eflag;
$html = preg_replace('/'.$rule.'/ism', '<?php if (\\1) { ?>', $html);
$rule = $that->btag.'elseif\s+([^'.$that->eflag.']+)\s*'.$that->eflag;
$html = preg_replace('/'.$rule.'/ism', '<?php } elseif (\\1) { ?>', $html);
$rule = $that->btag.'else\s*'.$that->eflag;
$html = preg_replace('/'.$rule.'/ism', '<?php } else { ?>', $html);
$rule = $that->btag.'loop\s+(\s+)\s+(\s+)\s*'.$that->eflag;
$html = preg_replace('/'.$rule.'/ism', '<?php foreach (\\1 as \\2) { ?>', $html);
$rule = $that->btag.'loop\s+(\s+)\s+(\s+)\s+(\s+)\s*'.$that->eflag;
$html = preg_replace('/'.$rule.'/ism', '<?php foreach (\\1 as \\2 => \\3) { ?>', $html);
$rule = $that->etag.'(if|loop)\s*'.$that->eflag;
$html = preg_replace('/'.$rule.'/ism', '<?php } ?>', $html);
$rule = $that->btag.'php\s*'.$that->eflag.'((?:(?!'.
$that->btag.')[\s\s]*?|(?r))*)'.$that->etag.'php\s*'.$that->eflag;
$html = preg_replace('/'.$rule.'/ism', '<?php \\1 ?>', $html);
return self::tag_execute($html);
}
static public function tag_list($attr, $html) {
if (!empty($html)) {
if (self::tag_havetag($html)) {
return self::tag_dealtag($attr, $html, true);
} else {
return self::tag_getdata($attr, $html, true);
}
} else {
exit('标签{list}的内容为空!');
}
}
static public function tag_data($attr, $html) {
if (!empty($html)) {
if (self::tag_havetag($html)) {
return self::tag_dealtag($attr, $html, false);
} else {
return self::tag_getdata($attr, $html, false);
}
} else {
exit('标签{data}的内容为空!');
}
}
static public function tag_execute($html) {
ob_clean(); ob_start();
if (!empty(self::$vars)) {
is_array(self::$vars) &&
extract(self::$vars, extr_overwrite);
}
$file_inc = website_dirinc.'/buffer/'.
md5(uniqid(rand(), true)).'.php';
if ($fp = fopen($file_inc, 'xb')) {
fwrite($fp, $html);
if (fclose($fp)) {
include($file_inc);
$html = ob_get_contents();
} unset($fp);
} else {
exit('模板解析文件生成失败!');
} ob_end_clean(); @unlink($file_inc);
return $html;
}
static private function tag_havetag($html) {
$bool_has = false;
$tpl_ins = new template();
self::$rule = $tpl_ins->btag.'([^'.$tpl_ins->eflag.']+)\/'.$tpl_ins->eflag;
$bool_has = $bool_has || preg_match('/'.self::$rule.'/ism', $html);
self::$rule = $tpl_ins->btag.'(\w+)\s*([^'.$tpl_ins->eflag.']*?)'.$tpl_ins->eflag.
'((?:(?!'.$tpl_ins->btag.')[\s\s]*?|(?r))*)'.$tpl_ins->etag.'\\1\s*'.$tpl_ins->eflag;
$bool_has = $bool_has || preg_match('/'.self::$rule.'/ism', $html);
unset($tpl_ins);
return $bool_has;
}
static private function tag_dealtag($attr, $html, $list) {
preg_match_all('/'.self::$rule.'/ism', $html, $out_matches);
if (!empty($out_matches[0])) {
$child_node = array();
for ($i = 0; $i < count($out_matches[0]); $i ++) {
$child_node[] = $out_matches[3][$i];
$html = str_ireplace($out_matches[3][$i], '{-->>child_node_'.$i.'<<--}', $html);
}
$html = self::tag_getdata($attr, $html, $list);
for ($i = 0; $i < count($out_matches[0]); $i ++) {
$html = str_ireplace('{-->>child_node_'.$i.'<<--}', $child_node[$i], $html);
}
preg_match_all('/'.self::$rule.'/ism', $html, $tmp_matches);
if (!empty($tmp_matches[0])) {
for ($i = 0; $i < count($tmp_matches[0]); $i ++) {
$callfunc = self::$prefix.ucfirst($tmp_matches[1][$i]);
if (method_exists('tags', $callfunc)) {
$temp = self::$callfunc($tmp_matches[2][$i], $tmp_matches[3][$i]);
$html = str_ireplace($tmp_matches[0][$i], $temp, $html);
}
}
}
unset($tmp_matches);
}
unset($out_matches); return $html;
}
static private function tag_getdata($attr, $html, $list=false) {
if (!empty($attr)) {
$attr_ins = new attbt($attr);
$attr_arr = $attr_ins->attrs;
if (is_array($attr_arr)) {
extract($attr_arr, extr_overwrite);
$source = table_name($source, $column);
$rule = '\[field:\s*(\w+)\s*([^\]]*?)\s*\/?]';
preg_match_all('/'.$rule.'/is', $html, $out_matches);
$data_str = '';
$data_ins = new datasql();
$attr_where = $attr_order = '';
if (!empty($where)) {
$where = str_replace(',', ' and ', $where);
$attr_where = ' where '. $where;
}
if (!empty($order)) {
$attr_order = ' order by '.$order;
} else {
$fed_name = '';
$fed_ins = $data_ins->getfedneedle($source);
$fed_cnt = $data_ins->getfedcount($fed_ins);
for ($i = 0; $i < $fed_cnt; $i ++) {
$fed_flag = $data_ins->getfedflag($fed_ins, $i);
if (preg_match('/auto_increment/ism', $fed_flag)) {
$fed_name = $data_ins->getfedname($fed_ins, $i);
break;
}
}
if (!empty($fed_name))
$attr_order = ' order by '.$fed_name.' desc';
}
if ($list == true) {
if (empty($source) && empty($sql)) {
exit('标签{list}必须指定source属性!');
}
$attr_rows = $attr_page = '';
if ($rows > 0) {
$attr_rows = ' limit 0,'.$rows;
}
if (!empty($sql)) {
$data_sql = $sql;
} else {
$data_sql = 'select * from `'.$source.'`'.
$attr_where.$attr_order.$attr_rows;
}
if ($pages=='true' && !empty($size)) {
$data_num = $data_ins->getrecnum($data_sql);
$page_cnt = ceil($data_num / $size);
global $page;
if (!isset($page) || $page < 1) $page = 1;
if ($page > $page_cnt) $page = $page_cnt;
$data_sql = 'select * from `'.$source.'`'.$attr_where.
$attr_order.' limit '.($page-1) * $size.','.$size;
$globals['cfg_page_curr'] = $page;
$globals['cfg_page_prev'] = $page - 1;
$globals['cfg_page_next'] = $page + 1;
$globals['cfg_page_nums'] = $page_cnt;
if (function_exists('list_pagelink')) {
$globals['cfg_page_list'] = list_pagelink($page, $page_cnt, 2);
}
}
$data_idx = 0;
$data_ret = $data_ins->sqlcmdexec($data_sql);
while ($row = $data_ins->getrecarr($data_ret)) {
if ($skip > 0 && !empty($flag)) {
$data_idx != 0 &&
$data_idx % $skip == 0 &&
$data_str .= $flag;
}
$data_tmp = $html;
$data_tmp = str_ireplace('@idx', $data_idx, $data_tmp);
for ($i = 0; $i < count($out_matches[0]); $i ++) {
$data_tmp = str_ireplace($out_matches[0][$i],
$row[$out_matches[1][$i]], $data_tmp);
}
$data_str .= $data_tmp; $data_idx ++;
}
} else {
if (empty($source)) {
exit('标签{data}必须指定source属性!');
}
$data_sql = 'select * from `'.$source.
'`'.$attr_where.$attr_order;
$row = $data_ins->getonerec($data_sql);
if (is_array($row)) {
$data_tmp = $html;
for ($i = 0; $i < count($out_matches[0]); $i ++) {
$data_val = $row[$out_matches[1][$i]];
if (empty($out_matches[2][$i])) {
$data_tmp = str_ireplace($out_matches[0][$i], $data_val, $data_tmp);
} else {
$attr_str = $out_matches[2][$i];
$attr_ins = new attbt($attr_str);
$func_txt = $attr_ins->attrs['function'];
if (!empty($func_txt)) {
$func_tmp = explode('(', $func_txt);
if (function_exists($func_tmp[0])) {
eval('$func_ret ='.str_ireplace('@me',
'\''.$data_val.'\'', $func_txt));
$data_tmp = str_ireplace($out_matches[0][$i], $func_ret, $data_tmp);
} else {
exit('调用了不存在的函数!');
}
} else {
exit('标签设置属性无效!');
}
}
}
$data_str .= $data_tmp;
}
}
unset($data_ins);
return $data_str;
} else {
exit('标签设置属性无效!');
}
} else {
exit('没有设置标签属性!');
}
}
static public function __callstatic($name, $args) {
exit('标签{'.$name.'}不存在!');
}
}
?>
模板引擎是mvc模式建立过程的重要方法,开发者可以设计一套赋予含义的标签,通过技术解析处理有效的把数据逻辑处理从界面模板中提取出来,通过解读标签的含义把控制权提交给相应业务逻辑处理程序,从而获取到需要的数据,以模板设计的形式展现出来,使设计人员能把精力更多放在表现形式上。下面是我对模板引擎的认识与设计方法:
说的好听些叫模板引擎,实际就是解读模板数据的过程(个人观点^^)。通过我对建站方面的思考认识,网站在展现形式上无非归纳为单条和多条两种形式,那么我们可以设定两种对应标签(如data、list)来处理这两种情况,关键点在于解决两种标签的多层相互嵌套问题,基本适合实现80%界面形式。
解读模板的方法有多种,常用的包括字符串处理(解决嵌套稍麻烦)、正则表达式。在这里我选用的正则表达式,下面是我的处理方法(本文仅提供思路和参考代码,可能不能直接使用)。
模板文件解析类:
复制代码 代码如下:
<?php
/*
* class: 模板解析类
* author: 51js.com-zmm
* date: 2011.3.1
* email: 304924248@qq.com
* blog: http://www.cnblogs.com/cnzmm/
*/
class template {
public $html, $vars, $btag, $etag;
public $bflag='{', $eflag='}', $pfix='zmm:';
private $folder, $file;
function __construct($vars=array()) {
!empty($vars) && $this->vars = $vars;
!empty($globals['cfg_tag_prefix']) &&
$this->pfix = $globals['cfg_tag_prefix'].':';
$this->btag = $this->bflag.$this->pfix;
$this->etag = $this->bflag.'\/'.$this->pfix;
empty(tags::$vars) && tags::$vars = &$this->vars;
}
public function loadtpl($tpl) {
$this->file = $this->gettplpath($tpl);
tags::$file = &$this->file;
if (is_file($this->file)) {
if ($this->gettplhtml()) {
$this->settpltags();
} else {
exit('模板文件加载失败!');
}
} else {
exit('模板文件['.$this->file.']不存在!');
}
}
private function gettplpath($tpl) {
$this->folder = website_dirroot.
$globals['cfg_tpl_root'];
return $this->folder.'/'.$tpl;
}
private function gettplhtml() {
$html = self::fmttplhtml(file_get_contents($this->file));
if (!empty($html)) {
$callfunc = tags::$prefix.'syntax';
$this->html = tags::$callfunc($html, new template());
} else {
exit('模板文件内容为空!');
} return true;
}
static public function fmttplhtml($html) {
return preg_replace('/(\r)|(\n)|(\t)|(\s{2,})/is', '', $html);
}
public function register($vars=array()) {
if (is_array($vars)) {
$this->vars = $vars;
tags::$vars = &$this->vars;
}
}
public function display($bool=false, $name="", $time=0) {
if (!empty($this->html)) {
if ($bool && !empty($name)) {
if (!is_int($time)) $time = 600;
$cache = new cache($time);
$cache->set($name, $this->html);
}
echo $this->html; flush();
} else {
exit('模板文件内容为空!');
}
}
public function setassign($souc, $info) {
if (!empty($this->html)) {
$this->html = str_ireplace($souc, self::fmttplhtml($info), $this->html);
} else {
exit('模板文件内容为空!');
}
}
private function settpltags() {
$this->setpaneltags(); $this->settrunktags(); $this->reghatchvars();
}
private function setpaneltags() {
$rule = $this->btag.'([^'.$this->eflag.']+)\/'.$this->eflag;
preg_match_all('/'.$rule.'/ism', $this->html, $out_matches);
$this->transtag($out_matches, 'panel'); unset($out_matches);
}
private function settrunktags() {
$rule = $this->btag.'(\w+)\s*([^'.$this->eflag.']*?)'.$this->eflag.
'((?:(?!'.$this->btag.')[\s\s]*?|(?r))*)'.$this->etag.'\\1\s*'.$this->eflag;
preg_match_all('/'.$rule.'/ism', $this->html, $out_matches);
$this->transtag($out_matches, 'trunk'); unset($out_matches);
}
private function transtag($result, $type) {
if (!empty($result[0])) {
switch ($type) {
case 'panel' : {
for ($i = 0; $i < count($result[0]); $i ++) {
$strtag = explode(' ', $result[1][$i], 2);
if (strpos($strtag[0], '.')) {
$itemarg = explode('.', $result[1][$i], 2);
$callfunc = tags::$prefix.ucfirst($itemarg[0]);
if (method_exists('tags', $callfunc)) {
$html = tags::$callfunc(chop($itemarg[1]));
if ($html !== false) {
$this->html = str_ireplace($result[0][$i], $html, $this->html);
}
}
} else {
$rule = '^([^\s]+)\s*([\s\s]+)$';
preg_match_all('/'.$rule.'/is', trim($result[1][$i]), $tmp_matches);
$callfunc = tags::$prefix.ucfirst($tmp_matches[1][0]);
if (method_exists('tags', $callfunc)) {
$html = tags::$callfunc($tmp_matches[2][0]);
if ($html !== false) {
$this->html = str_ireplace($result[0][$i], $html, $this->html);
}
} unset($tmp_matches);
}
} break;
}
case 'trunk' : {
for ($i = 0; $i < count($result[0]); $i ++) {
$callfunc = tags::$prefix.ucfirst($result[1][$i]);
if (method_exists('tags', $callfunc)) {
$html = tags::$callfunc($result[2][$i], $result[3][$i]);
$this->html = str_ireplace($result[0][$i], $html, $this->html);
}
} break;
}
default: break;
}
} else {
return false;
}
}
private function reghatchvars() {
$this->setpaneltags();
}
function __destruct() {}
}
?>
标签解析类:(目前暂时提供data、list两种标签的解析,说明思路)
复制代码 代码如下:
<?php
/*
* class: 标签解析类
* author: 51js.com-zmm
* date: 2011.3.2
* email: 304924248@qq.com
* blog: http://www.cnblogs.com/cnzmm/
*/
class tags {
static private $attrs=null;
static public $file, $vars, $rule, $prefix='tag_';
static public function tag_syntax($html, $that) {
$rule = $that->btag.'if\s+([^'.$that->eflag.']+)\s*'.$that->eflag;
$html = preg_replace('/'.$rule.'/ism', '<?php if (\\1) { ?>', $html);
$rule = $that->btag.'elseif\s+([^'.$that->eflag.']+)\s*'.$that->eflag;
$html = preg_replace('/'.$rule.'/ism', '<?php } elseif (\\1) { ?>', $html);
$rule = $that->btag.'else\s*'.$that->eflag;
$html = preg_replace('/'.$rule.'/ism', '<?php } else { ?>', $html);
$rule = $that->btag.'loop\s+(\s+)\s+(\s+)\s*'.$that->eflag;
$html = preg_replace('/'.$rule.'/ism', '<?php foreach (\\1 as \\2) { ?>', $html);
$rule = $that->btag.'loop\s+(\s+)\s+(\s+)\s+(\s+)\s*'.$that->eflag;
$html = preg_replace('/'.$rule.'/ism', '<?php foreach (\\1 as \\2 => \\3) { ?>', $html);
$rule = $that->etag.'(if|loop)\s*'.$that->eflag;
$html = preg_replace('/'.$rule.'/ism', '<?php } ?>', $html);
$rule = $that->btag.'php\s*'.$that->eflag.'((?:(?!'.
$that->btag.')[\s\s]*?|(?r))*)'.$that->etag.'php\s*'.$that->eflag;
$html = preg_replace('/'.$rule.'/ism', '<?php \\1 ?>', $html);
return self::tag_execute($html);
}
static public function tag_list($attr, $html) {
if (!empty($html)) {
if (self::tag_havetag($html)) {
return self::tag_dealtag($attr, $html, true);
} else {
return self::tag_getdata($attr, $html, true);
}
} else {
exit('标签{list}的内容为空!');
}
}
static public function tag_data($attr, $html) {
if (!empty($html)) {
if (self::tag_havetag($html)) {
return self::tag_dealtag($attr, $html, false);
} else {
return self::tag_getdata($attr, $html, false);
}
} else {
exit('标签{data}的内容为空!');
}
}
static public function tag_execute($html) {
ob_clean(); ob_start();
if (!empty(self::$vars)) {
is_array(self::$vars) &&
extract(self::$vars, extr_overwrite);
}
$file_inc = website_dirinc.'/buffer/'.
md5(uniqid(rand(), true)).'.php';
if ($fp = fopen($file_inc, 'xb')) {
fwrite($fp, $html);
if (fclose($fp)) {
include($file_inc);
$html = ob_get_contents();
} unset($fp);
} else {
exit('模板解析文件生成失败!');
} ob_end_clean(); @unlink($file_inc);
return $html;
}
static private function tag_havetag($html) {
$bool_has = false;
$tpl_ins = new template();
self::$rule = $tpl_ins->btag.'([^'.$tpl_ins->eflag.']+)\/'.$tpl_ins->eflag;
$bool_has = $bool_has || preg_match('/'.self::$rule.'/ism', $html);
self::$rule = $tpl_ins->btag.'(\w+)\s*([^'.$tpl_ins->eflag.']*?)'.$tpl_ins->eflag.
'((?:(?!'.$tpl_ins->btag.')[\s\s]*?|(?r))*)'.$tpl_ins->etag.'\\1\s*'.$tpl_ins->eflag;
$bool_has = $bool_has || preg_match('/'.self::$rule.'/ism', $html);
unset($tpl_ins);
return $bool_has;
}
static private function tag_dealtag($attr, $html, $list) {
preg_match_all('/'.self::$rule.'/ism', $html, $out_matches);
if (!empty($out_matches[0])) {
$child_node = array();
for ($i = 0; $i < count($out_matches[0]); $i ++) {
$child_node[] = $out_matches[3][$i];
$html = str_ireplace($out_matches[3][$i], '{-->>child_node_'.$i.'<<--}', $html);
}
$html = self::tag_getdata($attr, $html, $list);
for ($i = 0; $i < count($out_matches[0]); $i ++) {
$html = str_ireplace('{-->>child_node_'.$i.'<<--}', $child_node[$i], $html);
}
preg_match_all('/'.self::$rule.'/ism', $html, $tmp_matches);
if (!empty($tmp_matches[0])) {
for ($i = 0; $i < count($tmp_matches[0]); $i ++) {
$callfunc = self::$prefix.ucfirst($tmp_matches[1][$i]);
if (method_exists('tags', $callfunc)) {
$temp = self::$callfunc($tmp_matches[2][$i], $tmp_matches[3][$i]);
$html = str_ireplace($tmp_matches[0][$i], $temp, $html);
}
}
}
unset($tmp_matches);
}
unset($out_matches); return $html;
}
static private function tag_getdata($attr, $html, $list=false) {
if (!empty($attr)) {
$attr_ins = new attbt($attr);
$attr_arr = $attr_ins->attrs;
if (is_array($attr_arr)) {
extract($attr_arr, extr_overwrite);
$source = table_name($source, $column);
$rule = '\[field:\s*(\w+)\s*([^\]]*?)\s*\/?]';
preg_match_all('/'.$rule.'/is', $html, $out_matches);
$data_str = '';
$data_ins = new datasql();
$attr_where = $attr_order = '';
if (!empty($where)) {
$where = str_replace(',', ' and ', $where);
$attr_where = ' where '. $where;
}
if (!empty($order)) {
$attr_order = ' order by '.$order;
} else {
$fed_name = '';
$fed_ins = $data_ins->getfedneedle($source);
$fed_cnt = $data_ins->getfedcount($fed_ins);
for ($i = 0; $i < $fed_cnt; $i ++) {
$fed_flag = $data_ins->getfedflag($fed_ins, $i);
if (preg_match('/auto_increment/ism', $fed_flag)) {
$fed_name = $data_ins->getfedname($fed_ins, $i);
break;
}
}
if (!empty($fed_name))
$attr_order = ' order by '.$fed_name.' desc';
}
if ($list == true) {
if (empty($source) && empty($sql)) {
exit('标签{list}必须指定source属性!');
}
$attr_rows = $attr_page = '';
if ($rows > 0) {
$attr_rows = ' limit 0,'.$rows;
}
if (!empty($sql)) {
$data_sql = $sql;
} else {
$data_sql = 'select * from `'.$source.'`'.
$attr_where.$attr_order.$attr_rows;
}
if ($pages=='true' && !empty($size)) {
$data_num = $data_ins->getrecnum($data_sql);
$page_cnt = ceil($data_num / $size);
global $page;
if (!isset($page) || $page < 1) $page = 1;
if ($page > $page_cnt) $page = $page_cnt;
$data_sql = 'select * from `'.$source.'`'.$attr_where.
$attr_order.' limit '.($page-1) * $size.','.$size;
$globals['cfg_page_curr'] = $page;
$globals['cfg_page_prev'] = $page - 1;
$globals['cfg_page_next'] = $page + 1;
$globals['cfg_page_nums'] = $page_cnt;
if (function_exists('list_pagelink')) {
$globals['cfg_page_list'] = list_pagelink($page, $page_cnt, 2);
}
}
$data_idx = 0;
$data_ret = $data_ins->sqlcmdexec($data_sql);
while ($row = $data_ins->getrecarr($data_ret)) {
if ($skip > 0 && !empty($flag)) {
$data_idx != 0 &&
$data_idx % $skip == 0 &&
$data_str .= $flag;
}
$data_tmp = $html;
$data_tmp = str_ireplace('@idx', $data_idx, $data_tmp);
for ($i = 0; $i < count($out_matches[0]); $i ++) {
$data_tmp = str_ireplace($out_matches[0][$i],
$row[$out_matches[1][$i]], $data_tmp);
}
$data_str .= $data_tmp; $data_idx ++;
}
} else {
if (empty($source)) {
exit('标签{data}必须指定source属性!');
}
$data_sql = 'select * from `'.$source.
'`'.$attr_where.$attr_order;
$row = $data_ins->getonerec($data_sql);
if (is_array($row)) {
$data_tmp = $html;
for ($i = 0; $i < count($out_matches[0]); $i ++) {
$data_val = $row[$out_matches[1][$i]];
if (empty($out_matches[2][$i])) {
$data_tmp = str_ireplace($out_matches[0][$i], $data_val, $data_tmp);
} else {
$attr_str = $out_matches[2][$i];
$attr_ins = new attbt($attr_str);
$func_txt = $attr_ins->attrs['function'];
if (!empty($func_txt)) {
$func_tmp = explode('(', $func_txt);
if (function_exists($func_tmp[0])) {
eval('$func_ret ='.str_ireplace('@me',
'\''.$data_val.'\'', $func_txt));
$data_tmp = str_ireplace($out_matches[0][$i], $func_ret, $data_tmp);
} else {
exit('调用了不存在的函数!');
}
} else {
exit('标签设置属性无效!');
}
}
}
$data_str .= $data_tmp;
}
}
unset($data_ins);
return $data_str;
} else {
exit('标签设置属性无效!');
}
} else {
exit('没有设置标签属性!');
}
}
static public function __callstatic($name, $args) {
exit('标签{'.$name.'}不存在!');
}
}
?>