“多栏目分页”这个需求通常有两种理解:
- 一个栏目列表页,需要同时显示多个指定栏目下的文章列表,并且这些文章要混合在一起进行分页。 (首页的“新闻动态”板块,同时要显示“公司新闻”和“行业资讯”两个栏目的最新文章,并统一分页)
- 页(文章页)中,调用当前文章所在栏目以及其他几个相关栏目的文章列表,并进行分页。 (文章页右侧的“相关推荐”区域,来自多个栏目)
这两种场景的实现方法完全不同,下面我将分别对这两种情况进行详细说明。
多个栏目的文章混合分页(适用于首页、列表页)
这是最常见也最复杂的需求,核心思路是:通过自定义SQL查询,将多个指定栏目下的文章合并到一个结果集中,然后利用DedeCMS的 GetPageList 函数或手动处理分页逻辑来实现。
使用 GetPageList 函数(推荐,更简单)
GetPageList 是 DedeCMS 提供的一个强大的函数,可以执行任意SQL并返回分页后的结果。
修改列表页模板文件
找到你需要实现这个功能的列表页模板文件,通常是 templets/default/index.htm (首页) 或 templets/plus/list_栏目ID.htm (列表页)。
编写SQL语句和调用代码
在模板文件中,使用 {dede:sql} 标签来执行SQL,SQL的关键点在于:
- 使用
IN()语法来指定多个栏目ID。 - 使用
ORDER BY来定义文章的排序规则(通常是按发布时间降序)。 - 使用
limit来限制每次查询的数量,这是分页的关键。
示例代码:
假设我们要同时显示栏目ID为 1 (公司新闻) 和 2 (产品中心) 的文章,每页显示 10 篇。
{dede:sql sql="
SELECT arc.id, arc.title, arc.arcurl, arc.litpic, arc.pubdate, tp.typename
FROM dede_archives arc
LEFT JOIN dede_arctype tp ON arc.typeid = tp.id
WHERE arc.typeid IN (1, 2) AND arc.arcrank > -1
ORDER BY arc.pubdate DESC
limit 0, 10
"}
<li>
<a href="[field:arcurl/]" title="[field:title/]">[field:title function='cn_substr(@me,30)'/]</a>
<span class="date">[field:pubdate function='MyDate('Y-m-d', @me)'/]</span>
</li>
{/dede:sql}
实现真正的分页
上面的代码只实现了第一页,要实现真正的分页,你需要获取总记录数,并动态计算 limit 的偏移量,这通常需要结合PHP来完成,因为纯模板标签难以处理动态的 page 值。
更完整的实现方法(需要修改PHP文件):
-
创建一个自定义的PHP页面(
muti_list.php),放在plus/目录下。 -
编写PHP代码:
<?php require_once(dirname(__FILE__)."/../include/common.inc.php"); // 1. 获取分页参数 $page = isset($page) && is_numeric($page) ? $page : 1; $pagesize = 10; // 每页显示条数 // 2. 定义要查询的栏目ID数组 $typeids = array(1, 2); // 3. 构建SQL查询,获取总记录数 $typeid_sql = "typeid IN (".implode(',', $typeids).")"; $totalcount = $dsql->GetOne("SELECT COUNT(*) AS dd FROM `dede_archives` WHERE {$typeid_sql} AND arcrank > -1"); $totalcount = $totalcount['dd']; // 4. 计算总页数 $totalpage = ceil($totalcount / $pagesize); // 5. 确保当前页码不超过总页数 if ($page > $totalpage) $page = $totalpage; if ($page < 1) $page = 1; // 6. 计算数据偏移量 $start = ($page - 1) * $pagesize; // 7. 构建查询数据的SQL $sql = "SELECT arc.id, arc.title, arc.arcurl, arc.litpic, arc.pubdate, tp.typename FROM dede_archives arc LEFT JOIN dede_arctype tp ON arc.typeid = tp.id WHERE {$typeid_sql} AND arc.arcrank > -1 ORDER BY arc.pubdate DESC LIMIT {$start}, {$pagesize}"; // 8. 执行查询并循环输出 $dsql->SetQuery($sql); $dsql->Execute(); while ($row = $dsql->GetArray()) { // 这里是文章列表的HTML输出,你可以自定义样式 echo "<li><a href='{$row['arcurl']}'>{$row['title']}</a></li>"; } // 9. 输出分页条 $plist = ''; $geturl = "muti_list.php?page={page}"; $plist .= $pagefunclist->GetPageList($totalcount, $pagesize, $page, $geturl); echo "<div class='page'>".$plist."</div>"; ?> -
在模板中调用: 你可以将上面的PHP代码直接作为模板文件使用,或者通过
require方式在你的主模板中引入。
页调用多栏目的相关文章分页
这个需求相对简单,通常用于文章页的“相关推荐”模块,DedeCMS的 likearticle 标签本身就支持指定多个栏目。
页模板
通常是 templets/default/article_article.htm。
使用 likearticle 标签并指定栏目
likearticle 标签有一个 typeid 属性,可以传入多个栏目ID,用逗号隔开。
示例代码:
<div class="related-article">
<h3>相关推荐</h3>
{dede:likearticle row='8' typeid='1,3,5'}
<li>
<a href="[field:arcurl/]" title="[field:title/]">[field:title function='cn_substr(@me,30)'/]</a>
</li>
{/dede:likearticle}
</div>
关于分页:
likearticle 标签本身不支持分页,它一次性获取所有符合条件的文章,然后通过 row 属性限制显示的数量,如果你需要在这个模块里实现分页,你需要采用类似“场景一”的方法,为这个特定模块写一个独立的分页逻辑,但这会使页面变得非常复杂,通常不推荐,对于“相关推荐”模块,显示一个固定数量(如8-12条)的文章就足够了。
总结与注意事项
| 场景 | 核心方法 | 优点 | 缺点 |
|---|---|---|---|
| 多栏目混合分页 | 自定义PHP + SQL | 灵活、功能强大,能实现真正的分页 | 需要修改PHP文件,对新手有一定门槛 |
| 多栏目相关文章 | likearticle |
简单、快捷,纯模板实现 | 不支持分页,只能显示固定数量 |
重要注意事项:
- 栏目ID:请务必将代码中的
1, 2等数字替换为你自己网站实际的栏目ID。 - 表前缀:如果你的数据库表前缀不是默认的
dede_,请修改SQL中的表名。 - 性能:当栏目数量多或文章量巨大时,
IN()查询可能会对数据库造成一定压力,确保你的typeid字段有索引。 - 安全:在处理用户输入(如URL中的page参数)时,最好进行过滤和验证,防止SQL注入,上面的PHP示例中,
is_numeric($page)就是一个简单的安全措施。 - 缓存:频繁的复杂查询可能会影响网站速度,如果你的数据更新不频繁,可以考虑使用DedeCMS的缓存机制或第三方缓存插件来提升性能。
希望这个详细的解释能帮助你解决在DedeCMS中实现多栏目分页的问题!
