ECSHOP 本身只支持二级分类(一级分类和二级分类),要实现三级菜单,我们需要对 PHP 代码、CSS 样式 和 模板文件 进行修改。

下面我将提供一个完整、详细的步骤,并附上代码示例,你可以直接套用。
实现思路
-
PHP 逻辑修改:
- 修改获取分类数据的函数,使其能够读取并处理三级分类。
- 修改传递给模板的分类数据结构,确保模板能正确识别和显示三级分类。
-
模板文件修改:
- 在
library/page_header.lbi文件中,修改循环输出分类的代码,增加一个层级来判断和输出三级分类。
- 在
-
CSS 样式调整:
(图片来源网络,侵删)添加新的 CSS 样式来美化三级菜单,使其能够正确悬停和显示,并与一、二级菜单风格保持一致。
第一步:PHP 逻辑修改
这一步是核心,目的是让 ECSHOP 能“认识”并“提供”三级分类的数据。
修改 includes/lib_goods.php 文件
这个文件包含了获取商品分类的主要函数,我们需要修改 get_categories_tree() 函数。
操作步骤:

- 打开
includes/lib_goods.php文件。 - 找到
get_categories_tree()函数。 - 找到
if ($categories[$row['cat_id']]['parent_id'] == $parent_id)这一行。 - 在它下面,递归调用函数
get_categories_tree()的代码块中,进行修改。
修改前(原始代码片段):
// ... 函数内部 ...
foreach ($db->query($sql) as $row) {
// ...
if ($categories[$row['cat_id']]['parent_id'] == $parent_id) {
// ...
// 递归获取子分类
$children = get_categories_tree($categories[$row['cat_id']]['cat_id'], $level + 1);
if ($children) {
$categories[$row['cat_id']]['children'] = $children;
} else {
$categories[$row['cat_id']]['children'] = '';
}
// ...
}
}
// ...
修改后(支持三级分类):
我们需要确保递归调用能一直进行下去,直到没有子分类为止,ECSHOP 的原始代码逻辑上已经支持无限级,但问题出在数据读取和模板处理上,我们这里主要是确保数据结构完整。
关键在于,你需要确保你的数据库中,三级分类的 parent_id 指向了正确的二级分类 ID。
更稳妥的修改方式:
直接替换整个 get_categories_tree() 函数,这个函数在 ECSHOP 2.7.3 和其他版本中基本通用。
/**
* 获取分类树
* @param int $parent_id 父分类ID
* @param int $level 层级
* @return array 分类树数组
*/
function get_categories_tree($parent_id = 0, $level = 0)
{
$sql = "SELECT cat_id, cat_name, parent_id, is_show, grade, style, keywords, cat_desc " .
"FROM " . $GLOBALS['ecs']->table('category') .
" WHERE parent_id = '$parent_id' AND is_show = 1 ORDER BY sort_order ASC, cat_id ASC";
$res = $GLOBALS['db']->getAll($sql);
$arr = array();
foreach ($res AS $row) {
// 如果当前分类有子分类,则递归获取
if (get_categories_count($row['cat_id']) > 0) {
$row['children'] = get_categories_tree($row['cat_id'], $level + 1);
} else {
$row['children'] = ''; // 标记为叶子节点
}
$arr[] = $row;
}
return $arr;
}
这个版本的函数能正确地构建一个包含无限层级的分类树,如果你的分类结构是 一级 -> 二级 -> 三级,$row['children'] 就会包含三级分类的数组。
第二步:模板文件修改
现在数据已经准备好了,我们只需要在模板中把它显示出来。
修改 themes/你的模板名称/library/page_header.lbi 文件
这是网站头部文件,通常主导航菜单都在这里。
操作步骤:
- 打开
themes/你的模板名称/library/page_header.lbi文件。 - 找到输出分类的
foreach循环代码,它通常看起来像这样:
<!-- {foreach from=$categories item=cat} -->
<li class="nav-item">
<a href="{$cat.url}">{$cat.cat_name}</a>
<!-- {if $cat.children} -->
<div class="sub-category">
<!-- {foreach from=$cat.children item=child} -->
<a href="{$child.url}">{$child.cat_name}</a>
<!-- {/foreach} -->
</div>
<!-- {/if} -->
</li>
<!-- {/foreach} -->
修改后(支持三级菜单):
我们需要在二级分类的循环内部,再增加一个循环来判断和输出三级分类。
<!-- {foreach from=$categories item=cat} -->
<li class="nav-item">
<a href="{$cat.url}">{$cat.cat_name}</a>
<!-- {if $cat.children} -->
<div class="sub-category">
<!-- 循环二级分类 -->
<!-- {foreach from=$cat.children item=child} -->
<div class="second-level">
<a href="{$child.url}">{$child.cat_name}</a>
<!-- {if $child.children} -->
<div class="third-level">
<!-- 循环三级分类 -->
<!-- {foreach from=$child.children item=grandchild} -->
<a href="{$grandchild.url}">{$grandchild.cat_name}</a>
<!-- {/foreach} -->
</div>
<!-- {/if} -->
</div>
<!-- {/foreach} -->
</div>
<!-- {/if} -->
</li>
<!-- {/foreach} -->
代码解释:
- 我们给二级分类的外层
div添加了class="second-level"。 - 在二级分类的循环中,我们通过
<!-- {if $child.children} -->判断当前二级分类下是否有三级分类。 - 如果有,我们就创建一个新的
div并赋予class="third-level",然后在这个div内部用另一个foreach循环输出所有三级分类。
第三步:CSS 样式美化
为了让三级菜单看起来更专业,我们需要添加 CSS 样式,你可以将这些样式添加到你的模板主 CSS 文件中(themes/你的模板名称/style.css)。
/* 1. 隐藏所有二级和三级菜单,默认只显示一级 */
.sub-category, .third-level {
display: none;
position: absolute;
left: 100%; /* 让三级菜单出现在二级菜单的右侧 */
top: 0;
background-color: #fff;
border: 1px solid #ddd;
padding: 10px;
min-width: 160px;
z-index: 1000;
}
/* 2. 当鼠标悬停在一级菜单上时,显示对应的二级菜单 */
.nav-item:hover .sub-category {
display: block;
}
/* 3. 二级菜单项的样式 */
.second-level {
position: relative; /* 为三级菜单定位提供参考 */
padding: 5px 10px;
white-space: nowrap; /* 防止文字换行 */
}
.second-level a {
display: block;
color: #333;
text-decoration: none;
padding: 5px 0;
}
.second-level a:hover {
color: #ff6600;
text-decoration: underline;
}
/* 4. 三级菜单的样式 */
.third-level {
/* 样式已经在上面定义,这里可以补充或覆盖 */
left: 100%; /* 确保在二级菜单右侧显示 */
top: 0;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
.third-level a {
display: block;
padding: 3px 10px;
color: #666;
text-decoration: none;
font-size: 14px;
}
.third-level a:hover {
color: #ff6600;
background-color: #f9f9f9;
}
CSS 样式说明:
display: none;: 默认隐藏二级和三级菜单。hover: 这是 CSS 的核心,当鼠标悬停在.nav-item(一级菜单) 上时,它的子元素.sub-category(二级菜单) 会显示 (display: block;)。position: absolute;和left: 100%;: 这两个属性是让三级菜单“飞”到二级菜单右侧的关键。absolute让它脱离文档流,left: 100%让它的左边框对准父级元素的右边框。.second-level: 为每个二级分类项添加了position: relative,这样里面的.third-level就能相对于它来定位。z-index: 确保菜单显示在其他页面元素之上。
总结与注意事项
- 检查分类数据:在动手修改代码前,请务必去 ECSHOP 后台 -> 商品分类 -> 分类管理,确保你的分类层级关系是正确的(
手机->品牌->苹果)。 - 清除缓存:修改完 PHP 和模板文件后,一定要去 ECSHOP 后台 -> 清除缓存,否则看不到效果。
- 模板兼容性:不同的 ECSHOP 模板(如官方默认模板、第三方模板)其
page_header.lbi文件的结构可能略有不同,请根据你实际文件中的代码进行修改,核心逻辑(嵌套foreach)不变。 - 浏览器兼容性:上述 CSS 代码在现代浏览器中(Chrome, Firefox, Edge, Safari)都能很好地工作,如果需要支持非常古老的浏览器(如 IE),可能需要添加一些额外的 hack 或调整。
按照以上三个步骤,你就可以成功地在你的 ECSHOP 网站上实现一个功能完善、样式美观的三级菜单了。
