cattree 是一个底层函数,主要用于在后台管理界面中,以树形结构展示所有的栏目(频道),这对于拥有大量栏目的网站来说,是组织和管理内容的核心。

(图片来源网络,侵删)
下面我将通过一个完整的示例,从底层原理到实际应用,带你彻底理解 cattree。
cattree 的核心作用
cattree 的作用就是:
从数据库中读取所有栏目信息,并根据它们的层级关系(topid 字段),生成一个具有缩进、可折叠/展开的HTML列表。
这个函数通常用在需要用户选择栏目的地方,
- 发布文章时选择栏目
- 添加自定义链接时选择目标栏目
- 在模板中调用栏目导航时(虽然前台更多用
{dede:channel}
底层函数解析 ( /include/common.func.php )
打开 include/common.func.php 文件,你可以找到 cattree 函数的定义,下面是一个简化版的解析,让你明白它的工作原理。

(图片来源网络,侵删)
/**
* 生成一个下拉式的树形目录选择菜单
*
* @param string $fieldname 下拉菜单的名称
* @param string $myvalue 当前选中的栏目ID
* @param string $style 样式,如 'select'(下拉框)或 'tree'(树形列表)
* @param string $sel 额外的属性,如 'onchange="somefunction()"'
* @param string $typeid 父栏目ID,用于只显示其子栏目
* @return string 生成的HTML代码
*/
function cattree($fieldname, $myvalue = 0, $style = 'select', $sel = '', $typeid = 0)
{
global $dsql;
$myvalue = isset($myvalue) ? $myvalue : 0;
$types = '';
// 获取栏目数据
// $sql = "SELECT id,typename,reid,issign FROM `#@__arctype` WHERE ishidden<>1 ORDER BY sortrank ASC";
$sql = "SELECT id,typename,reid,issign FROM `#@__arctype` WHERE ishidden<>1 ORDER BY sortrank ASC";
$dsql->SetQuery($sql);
$dsql->Execute('me');
// 将数据读入一个数组,方便后续处理
$options = array();
while ($row = $dsql->GetArray('me')) {
$options[$row['id']] = $row;
}
// 递归函数,用于生成树形结构的HTML
// 这是 cattree 的核心逻辑
function GetCatTree($options, $typeid = 0, $myvalue = 0, $space = '')
{
$types = '';
foreach ($options as $row) {
if ($row['reid'] == $typeid) {
$selected = ($row['id'] == $myvalue) ? "selected='selected'" : '';
$types .= "<option value='{$row['id']}' {$selected}>{$space}{$row['typename']}</option>";
// 递归调用,查找子栏目
$types .= GetCatTree($options, $row['id'], $myvalue, $space . ' ');
}
}
return $types;
}
// 调用递归函数生成最终的HTML
$types = "<select name='$fieldname' id='$fieldname' $sel>\n";
$types .= "<option value='0'>请选择栏目...</option>\n";
$types .= GetCatTree($options, $typeid, $myvalue);
$types .= "</select>\n";
return $types;
}
代码逻辑解读:
-
参数:
$fieldname: 生成的<select>元素的name和id,这是表单提交时用来识别这个字段的。$myvalue: 当前已经选中的栏目ID,函数会自动为这个栏目添加selected属性。$style: 虽然函数定义里有,但在标准实现中,这个参数通常被忽略,默认生成下拉框。$sel: 可以给<select>元素添加额外的属性,onchange事件。$typeid: 如果指定了,则只显示此ID栏目的子栏目,而不是所有栏目。
-
数据获取:
- 函数通过
$dsql查询#@__arctype表(栏目表),获取所有ishidden<>1(非隐藏)的栏目。 - 查询结果按
sortrank(排序)升序排列。
- 函数通过
-
核心递归
GetCatTree:
(图片来源网络,侵删)- 这个内部函数是构建树形结构的关键。
- 它遍历所有栏目,寻找
reid(父栏目ID)等于当前$typeid的栏目。 - 找到后,生成一个
<option>标签,并用$space变量(空格或 )来模拟缩进,体现层级关系。 - 它递归调用自身,将当前栏目的
id作为新的$typeid去查找其子栏目,并将缩进$space加长一层。 - 这个递归过程会一直持续,直到没有子栏目为止,从而完美地构建出整个栏目树。
实际应用示例
在后台发布文章模板中应用
这是 cattree 最经典的应用场景,打开 dede/templets/article_add.htm 文件,找到选择栏目的部分,你会看到类似这样的代码:
<tr>
<td height="26" colspan="2" bgcolor="#f8f8f8">
<strong>选择栏目:</strong>
<span id='typeidct'></span>
<select name='typeid' id='typeid' style='width:200px' onchange="ShowCatMap(this.value);">
<option value='0'>请选择栏目...</option>
{dede:global name='cattree' function='cattree("typeid",@me,0,"onchange=\"ShowCatMap(this.value);\"")'/}
</select>
</td>
</tr>
代码解析:
<select name='typeid' ...>:这是一个标准的下拉选择框。{dede:global name='cattree' ...}:这是调用我们上面分析的cattree函数。function='cattree(...)':明确指定调用cattree这个自定义函数。"typeid":传递给函数的第一个参数$fieldname,所以生成的下拉框name和id都是typeid,发布文章时,表单会通过typeid这个键来获取你选择的栏目ID。@me:这是织梦模板的一个特殊变量,在这里它代表当前文章所属的栏目ID,如果是在编辑一篇已有文章的页面,@me就是这篇文章的typeid,cattree函数会自动选中这个栏目,如果是新增文章,@me为空,则默认不选中任何栏目。0:对应$style参数,这里没什么用。"onchange=\"ShowCatMap(this.value);\"":对应$sel参数,它给<select>元素添加了一个onchange事件,当用户选择栏目时,会调用一个JavaScript函数ShowCatMap,这个函数通常会用来动态加载该栏目下的子级分类(如果启用)。
在自定义后台页面中手动调用
假设你要创建一个新的后台功能页面,dede/my_special_add.php,你需要让用户选择一个目标栏目,你可以在对应的模板文件 dede/templets/my_special_add.htm 中这样使用:
<div class="item">
<label>所属栏目:</label>
<!--
name='target_catid':表单提交的字段名
value='0':默认不选中任何栏目
onchange="alert('你选择了:' + this.value)":自定义一个简单的响应
-->
{dede:global name='cattree' function='cattree("target_catid", 0, 0, "onchange=\"alert(\'你选择了:\' + this.value)\"")'/}
</div>
当你提交这个表单时,PHP代码可以通过 $_POST['target_catid'] 获取到用户选择的栏目ID。
总结与关键点
- 功能定位:
cattree是一个后台管理专用的底层函数,用于生成栏目选择器。 - 核心机制:它通过递归算法,根据栏目表中的
reid(父ID)和id(自身ID)字段关系,构建出有缩进的树形HTML列表(通常是<select>)。 - 参数理解:
$fieldname是必须的,它定义了表单字段的名称。$myvalue用于实现回显,让用户能看到当前选中的是什么。
- 前台使用:如果你想在网站前台的页面上显示一个栏目导航树,你应该使用
{dede:channel}标签,并配合typeid、reid等属性来控制显示范围,而不是使用cattree。cattree主要是为表单交互设计的。
通过以上示例和解析,你应该已经对织梦的 cattree 函数有了全面的理解,它虽然只是一个简单的函数,但却是织梦后台内容管理流程中不可或缺的一环。
