捣鼓了两天才弄出来,不熟悉,有可以改进的地方,需要的可以下载
先贴效果图

<?php
namespace Common\TagLib;
use Think\Template\TagLib;
/**
* Zui 标签库
*/
class Zui extends TagLib {
/**
* 定义标签列表
* @var array
*/
protected $tags = array('votree' => array(
'attr' => 'name,id,offset,length,key,mod',
'level' => 3
));
/**
* votree标签解析 循环输出数据集树
* 格式:
* <votree name="userList" id="user" empty="" >
* {user.username}
* {user.email}
* </votree>
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @return string|void
*/
public function _votree($tag, $content) {
$name = $tag['name'];
$id = $tag['id'];
$empty = isset($tag['empty']) ? $tag['empty'] : '';
$key = !empty($tag['key']) ? $tag['key'] : 'i';
$mod = isset($tag['mod']) ? $tag['mod'] : '2';
// 允许使用函数设定数据集 <volist name=":fun('arg')" id="vo">{$vo.name}</volist>
$parseStr = '<?php ';
if (0 === strpos($name, ':')) {
$parseStr .= '$_result=' . substr($name, 1) . ';';
$name = '$_result';
}
else {
$name = $this -> autoBuildVar($name);
}
$parseStr .= 'if(is_array(' . $name . ')): $' . $key . ' = 0;';
if (isset($tag['length']) && '' != $tag['length']) {
$parseStr .= ' $__LIST__ = array_slice(' . $name . ',' . $tag['offset'] . ',' . $tag['length'] . ',true);';
}
elseif (isset($tag['offset']) && '' != $tag['offset']) {
$parseStr .= ' $__LIST__ = array_slice(' . $name . ',' . $tag['offset'] . ',null,true);';
}
else {
$parseStr .= ' $__LIST__ = ' . $name . ';';
}
$parseStr .= 'if( count($__LIST__)==0 ) : echo "' . $empty . '" ;';
$parseStr .= 'else: ';
$parseStr .= 'zui_votree(';
$parseStr .= 'function($' . $key . ',$' . $id . ',$mod,$contype){ ?>';
$parseStr .= $this -> tpl -> parse($content);
$parseStr .= '<?php }';
$parseStr .= ',';
$parseStr .= '$__LIST__';
$parseStr .= ',';
$parseStr .= $mod;
$parseStr .= '); ?>';
$parseStr .= '<?php endif; else: echo "' . $empty . '" ;endif; ?>';
if (!empty($parseStr)) {
return $parseStr;
}
return;
}
}list_to_tree函数代码/**
* 把返回的数据集转换成Tree
* @param array $list 要转换的数据集
* @param string $pid parent标记字段
* @param string $level level标记字段
* @return array
*/
function list_to_tree($list, $pk = 'id', $pid = 'pid', $child = '_child', $root = 0) {
// 创建Tree
$tree = array();
if (is_array($list)) {
// 创建基于主键的数组引用
$refer = array();
foreach ($list as $key => $data) {
$refer[$data[$pk]] = &$list[$key];
}
foreach ($list as $key => $data) {
// 判断是否存在parent
$parentId = $data[$pid];
if ($root == $parentId) {
$tree[] = &$list[$key];
}
else {
if (isset($refer[$parentId])) {
$parent = &$refer[$parentId];
$parent[$child][] = &$list[$key];
}
}
}
}
return $tree;
}zui_votree函数实现/**
* zui_votree循环
* $content 模版循环内容
* $treedata为list_to_tree的结果
* $callback参数 $key,$id,$mod,$contype(0中间、1开始、2结束)
*/
function zui_votree($callback, $treedata, $mod, $pk = 'id', $pid = 'pid', $child = '_child', $root = 0) {
$i = 0;
$j = count($treedata);
if ($j > 0) {
$j = $j - 1;
foreach ($treedata as $tempkey => $tempid) {
$modval = $tempkey % $mod;
$haschild = (is_array($tempid) && !empty($tempid[$child]));
if ($haschild) {
call_user_func($callback, $tempkey, $tempid, $modval, 1);
}
else
call_user_func($callback, $tempkey, $tempid, $modval, 0);
if (is_array($tempid) && !empty($tempid[$child])) {
$res .= zui_votree($callback, $tempid[$child], $mod, $pk, $pid, $child, $root);
}
++$tempkey;
if ($haschild)
call_user_func($callback, $tempkey, $tempid, $modval, 2);
}
}
}使用方法<ul class="tree tree-lines tree-chevrons" data-ride="tree">
<zui:votree name="_data" id="group">
<switch name="contype" >
<case value="1">
<li>
<a href="#">{$group.title}2</a>
<ul>
</case>
<case value="2">
</ul>
</li>
</case>
<default />
<li>
<a href="#">{$group.title}1</a>
</li>
</switch>
</zui:votree>
</ul> 