- 获取当前栏目的 ID。
- 根据当前栏目 ID,查询其父栏目的信息。
- 再根据上一步获取的父栏目 ID,查询其父栏目的信息,这就是“上上级栏目”。
下面我将提供几种常用的方法,从最推荐到最不推荐,并解释其原理。

(图片来源网络,侵删)
使用 GetTopParent() 函数(推荐)
这是最简洁、最官方、性能也最好的方法,DedeCMS 内置了一个专门用于获取顶级栏目的函数 GetTopParent(),我们可以利用它来获取指定栏目的顶级栏目,如果该顶级栏目不是当前栏目的直接父栏目,那么它就是我们的“上上级栏目”。
适用场景: 当你的栏目层级是 顶级栏目 > 上上级栏目 > 上级栏目 > 当前栏目 这种固定层级时,此方法非常高效。
代码示例:
假设这段代码需要放在一个列表页(list_article.htm页(article_article.htm)中。

(图片来源网络,侵删)
<?php
// 1. 获取当前栏目的ID
$cid = $GLOBALS['cfg_arcclassid'];
// 如果是在列表页,也可以这样获取:
// $cid = $this->TypeID;
// 2. 使用 GetTopParent() 函数获取顶级栏目信息
$topParent = GetTopParent($cid);
// 3. 获取顶级栏目的ID
$topParentId = $topParent['id'];
// 4. 获取当前栏目的直接父栏目信息
$parentInfo = GetOneType($cid);
// 5. 获取直接父栏目的ID
$parentId = $parentInfo['reid']; // reid 字段存储的是父栏目的ID
// 6. 判断:如果顶级栏目的ID不等于直接父栏目的ID,说明存在上上级栏目
if ($topParentId != $parentId) {
// $topParent 就是上上级栏目的信息
$grandParentId = $topParentId;
$grandParentName = $topParent['typename'];
$grandParentUrl = GetTypeUrl($topParent['id'], $topParent['typedir'], $topParent['isdefault'], $topParent['defaultname'], $topParent['ispart'], $topParent['namerule'], $topParent['namerule2']);
// --- 输出结果 ---
echo "上上级栏目ID: " . $grandParentId . "<br>";
echo "上上级栏目名称: " . $grandParentName . "<br>";
echo "上上级栏目链接: " . $grandParentUrl . "<br>";
// 如果你需要上上级栏目的其他字段,可以直接从 $topParent 数组中获取,
// $grandParentDescription = $topParent['description'];
} else {
// 如果顶级栏目就是直接父栏目,说明当前栏目没有上上级栏目(或者在二级栏目下)
echo "当前栏目没有上上级栏目。";
}
?>
手动查询数据库(通用且灵活)
GetTopParent() 函数不满足你的需求(栏目层级不固定,或者你只需要上上级栏目,而不是顶级栏目),你可以手动查询 dede_arctype 数据表。
原理:
- 从
dede_arctype表中根据当前栏目 ID (id) 找到它的父栏目 ID (reid)。 - 再用这个父栏目 ID 作为查询条件,在
dede_arctype表中查找,得到的结果就是上上级栏目。
代码示例:
<?php
// 1. 获取当前栏目的ID
$cid = $GLOBALS['cfg_arcclassid'];
// 2. 查询当前栏目的信息,以获取其父栏目ID (reid)
$dsql->SetQuery("SELECT reid FROM dede_arctype WHERE id = {$cid}");
$dsql->Execute();
$parentRow = $dsql->GetArray();
$parentId = $parentRow['reid'];
// 3. 判断是否存在父栏目
if (empty($parentId)) {
echo "当前栏目没有父栏目,因此也没有上上级栏目。";
} else {
// 4. 根据父栏目ID,查询上上级栏目的信息
$dsql->SetQuery("SELECT * FROM dede_arctype WHERE id = {$parentId}");
$dsql->Execute();
$grandParentRow = $dsql->GetArray();
// 5. 判断上上级栏目是否存在(理论上只要父栏目存在,上上级栏目就应该存在,除非父栏目是顶级栏目)
if (empty($grandParentRow)) {
echo "当前栏目的父栏目是顶级栏目,没有上上级栏目。";
} else {
// --- 输出结果 ---
$grandParentId = $grandParentRow['id'];
$grandParentName = $grandParentRow['typename'];
$grandParentUrl = GetTypeUrl($grandParentRow['id'], $grandParentRow['typedir'], $grandParentRow['isdefault'], $grandParentRow['defaultname'], $grandParentRow['ispart'], $grandParentRow['namerule'], $grandParentRow['namerule2']);
echo "上上级栏目ID: " . $grandParentId . "<br>";
echo "上上级栏目名称: " . $grandParentName . "<br>";
echo "上上级栏目链接: " . $grandParentUrl . "<br>";
}
}
?>
使用 GetOneType() 函数(适用于已知父栏目ID)
这个方法和方法二的原理非常相似,只是第一步查询当前栏目信息时,使用了 DedeCMS 的封装函数 GetOneType()。

(图片来源网络,侵删)
代码示例:
<?php
// 1. 获取当前栏目的ID
$cid = $GLOBALS['cfg_arcclassid'];
// 2. 使用 GetOneType() 获取当前栏目的完整信息
$currentType = GetOneType($cid);
// 3. 从信息中获取父栏目ID
$parentId = $currentType['reid'];
// 4. 如果存在父栏目,则继续查询上上级栏目
if (!empty($parentId)) {
// 5. 使用 GetOneType() 获取上上级栏目的信息
$grandParentType = GetOneType($parentId);
if (!empty($grandParentType)) {
// --- 输出结果 ---
echo "上上级栏目ID: " . $grandParentType['id'] . "<br>";
echo "上上级栏目名称: " . $grandParentType['typename'] . "<br>";
echo "上上级栏目链接: " . GetTypeUrl($grandParentType['id'], $grandParentType['typedir'], $grandParentType['isdefault'], $grandParentType['defaultname'], $grandParentType['ispart'], $grandParentType['namerule'], $grandParentType['namerule2']) . "<br>";
} else {
echo "当前栏目的父栏目是顶级栏目。";
}
} else {
echo "当前栏目没有父栏目。";
}
?>
总结与建议
| 方法 | 优点 | 缺点 | 推荐场景 |
|---|---|---|---|
方法一 GetTopParent() |
代码最简洁,性能最好,官方推荐 | 只能获取到顶级栏目,如果栏目层级超过3级,它无法精确获取“上上级”,而是获取到“顶级”。 | 栏目层级固定,且只需要获取顶级栏目作为上上级时。 |
| 方法二 手动查询 | 逻辑清晰,通用性强,可以精确控制查询层级。 | 需要手动写 SQL 语句,代码稍多。 | 对栏目层级没有固定要求,或者需要更复杂的逻辑判断时。 |
方法三 GetOneType() |
代码比方法二简洁,利用了Dede封装函数。 | 仍然需要调用两次函数,性能略逊于方法一(但影响不大)。 | 不想写原生 SQL,且认为 GetOneType() 更符合 DedeCMS 的编程习惯时。 |
最终建议:
- 如果你的网站栏目结构非常规范,且“上上级栏目”顶级栏目”,请优先使用方法一。
- 如果你的栏目结构比较灵活,或者你需要的是真正的“上上级”而不是“顶级”,请使用方法二或方法三,方法二更底层,方法三更“面向对象”一些,两者都可以。
