这是一个非常常见的需求,因为首页内容(如推荐文章、热门文章等)如果太多,会导致页面加载缓慢,影响用户体验和SEO,首页分页可以有效解决这个问题。

(图片来源网络,侵删)
下面我将提供两种最主流的实现方法:
- 推荐方法:使用自定义SQL + 自定义标签,这种方法最灵活,性能最好,也是目前官方和社区最推荐的方式。
- 传统方法:修改系统核心文件,这种方法比较古老,不推荐用于新项目,因为会破坏系统文件,不利于升级和维护,但了解它有助于你理解Dede的工作原理。
使用自定义SQL + 自定义标签(推荐)
这种方法的核心思想是:绕过Dede默认的首页调用逻辑,直接在首页模板中执行我们自定义的SQL查询,并使用自定义标签来显示分页。
步骤1:准备数据(以调用“推荐文章”为例)
我们假设首页需要调用 dede_archives 表中 ismake = 1(推荐)的文章,并实现分页。
步骤2:创建自定义函数文件
为了安全地执行SQL,我们需要在Dede的函数库中添加一个自定义函数。

(图片来源网络,侵删)
- 打开
/include/common.func.php文件。 - 在文件末尾
?>之前,添加以下PHP函数代码:
/**
* 获取首页指定条件的文章列表及分页
* @param string $typeid 栏目ID,0为所有
* @param string $flag 推荐标识,如 'c' (推荐)
* @param int $pagesize 每页显示条数
* @return array 返回包含 'list' 和 'page' 的数组
*/
function GetIndexArcList($typeid = '0', $flag = '', $pagesize = 10) {
global $dsql, $cfg_list_son;
$innertext = GetSysTemplets('list_fulllist.htm');
// 1. 获取总记录数,用于计算总页数
$addsql = "";
if ($typeid != 0) {
if ($cfg_list_son == 'N') {
$addsql .= " AND (typeid='$typeid') ";
} else {
$addsql .= " AND (typeid IN (SELECT id FROM `dede_arctype` WHERE reid='$typeid' OR id='$typeid')) ";
}
}
if ($flag != '') {
$addsql .= " AND (flag LIKE '%{$flag}%') ";
}
$totalquery = "SELECT COUNT(*) AS dd FROM `dede_archives` WHERE arcrank > -1 $addsql";
$totalrow = $dsql->GetOne($totalquery);
$totalcount = $totalrow['dd'];
// 2. 获取分页参数
$page = isset($_GET['page']) && is_numeric($_GET['page']) ? intval($_GET['page']) : 1;
$totalpage = ceil($totalcount / $pagesize);
// 3. 获取本页数据
$start = ($page - 1) * $pagesize;
$addsql .= " ORDER BY id DESC LIMIT $start, $pagesize";
$query = "SELECT * FROM `dede_archives` WHERE arcrank > -1 $addsql";
$dsql->SetQuery($query);
$dsql->Execute();
$artlist = '';
while ($row = $dsql->GetArray()) {
$artlist .= GetListHtml($row, $innertext);
}
// 4. 获取分页链接
$pagena = '';
$geturl = "http://".$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'];
if ($typeid != 0) {
$geturl .= "?typeid=$typeid";
}
// 引入分页类
require_once(DEDEINC.'/datalistcp.class.php');
$dl = new DataListCP();
$dl->pageSize = $pagesize;
$dl->SetTemplate($geturl); // 设置分页链接地址
$dl->SetSource($totalcount); // 设置总记录数
$dl->SetListName('artlist'); // 设置列表名称
$dl->SetPageLinkType(1); // 设置分页链接类型,1为普通
$pagena = $dl->GetPageList();
return array(
'list' => $artlist,
'page' => $pagena
);
}
/**
* 根据文章数据生成列表项HTML
* @param array $row 文章数据
* @param string $innertext 模板内容
* @return string
*/
function GetListHtml($row, $innertext) {
// 这里简化处理,实际项目中应该调用更完整的函数如 GetOneArc
$arcUrl = GetOneArchive($row['id']);
$pubdate = MyDate('Y-m-d H:i', $row['pubdate']);
$str = "
<li>
<a href=\"{$arcUrl['arcurl']}\">{$row['title']}</a>
<span class=\"time\">{$pubdate}</span>
</li>";
return $str;
}
代码解释:
GetIndexArcList()是核心函数,它接收栏目ID、推荐标志和每页条数作为参数。- 它首先计算符合条件的总文章数,从而得到总页数。
- 然后根据当前页码
page,使用LIMIT子句查询出当前页的文章数据。 - 它使用
datalistcp.class.php这个Dede自带的分页类来生成分页链接。 - 函数返回一个包含文章列表HTML和分页HTML的数组。
步骤3:修改首页模板文件 (index.htm)
- 打开你的首页模板文件,通常位于
/templets/default/index.htm。 - 找到你想要显示分页列表的位置,将原来的Dede标签(如
{dede:arclist})替换为以下代码:
<div class="main">
<h2>推荐文章</h2>
<ul class="article-list">
<!-- {dede:php} -->
// 调用我们刚才创建的自定义函数
// 获取ID为0的所有栏目下的推荐(c)文章,每页10条
$result = GetIndexArcList('0', 'c', 10);
// 输出文章列表
echo $result['list'];
// {/dede:php}
</ul>
<!-- 分页导航 -->
<div class="page-nav">
<!-- {dede:php} -->
// 输出分页链接
echo $result['page'];
// {/dede:php}
</div>
</div>
代码解释:
- 我们使用
{dede:php}...{/dede:php}标签来执行PHP代码。 - 在里面调用
GetIndexArcList()函数,并传入你需要的参数。 - 将函数返回的
list部分输出到文章列表的<ul>中。 - 将返回的
page部分输出到分页导航的<div>中。
步骤4:清理缓存并测试
- 进入DedeCMS后台 -> 系统 -> 一键更新网站 -> 更新主页HTML。
- 在更新主页时,勾选“更新主页HTML”和“生成所有栏目”。
- 更新完成后,访问你的首页,你应该就能看到推荐文章列表和底部的分页链接了,点击第二页,URL会变成
http://你的域名/index.php?page=2会相应变化。
修改系统核心文件(不推荐,仅作了解)
这种方法通过修改 index.php 文件,让首页也支持 list 页面那样的分页逻辑。
步骤1:修改 /index.php
- 找到
index.php文件。 - 找到类似这样的代码段(通常在文件末尾):
//更新主页
if($dopost=='updatehome')
{
require_once(DEDEINC."/arc.partview.class.php");
$GLOBALS['_arclistEnv'] = 'index';
$row = $dsql->GetOne("Select * From `dede_homepageset`");
$tmpfile = tempdir($row['templet']);
$pv = new PartView($tmpfile);
$pv->SetTemplet($cfg_basedir.$row['templet']);
$pv->SaveToHtml($cfg_basedir.$cfg_indexname);
echo "成功更新主页!";
exit();
}
- 在
exit();之前,添加以下代码来处理分页逻辑:
// ... 原有代码 ...
// 处理首页分页
if(empty($dopost))
{
$page = isset($_GET['page']) && is_numeric($_GET['page']) ? intval($_GET['page']) : 1;
$typeid = isset($_GET['typeid']) ? intval($_GET['typeid']) : 0;
// 设置首页每页显示条数
$pagesize = 10;
// 调用栏目列表页模板,并传入参数
// 这里我们直接调用一个列表页模板来显示首页内容
// 你需要提前创建一个列表模板,/templets/default/list_index.htm
$tempfile = $cfg_basedir.$cfg_templets_dir."/default/list_index.htm";
if(!file_exists($tempfile))
{
die("模板文件不存在,请检查路径:".$tempfile);
}
require_once(DEDEINC."/arc.listview.class.php");
$lv = new ListView($typeid,$page,$pagesize,$tempfile);
$lv->Display();
exit();
}
// ... 原有代码 ...
步骤2:创建新的列表模板 (list_index.htm)
- 在你的模板目录
/templets/default/下,新建一个文件list_index.htm。 - 将你原来首页模板中需要分页的部分(
{dede:arclist})复制到list_index.htm中。 - 重要:在
list_index.htm的末尾,添加Dede的分页标签:
<!-- list_index.htm 文件内容示例 -->
{dede:arclist flag='c' titlelen=40 row=10}
<li><a href="[field:arcurl/]">[field:title/]</a></li>
{/dede:arclist}
<!-- 在这里添加分页标签 -->
<div class="page-nav">
{dede:pagelist listsize=4 listitem="info,index,end,pre,next,pageno"}
</div>
步骤3:清理缓存并测试
- 进入后台,系统 -> 一键更新网站 -> 更新主页HTML。
- 访问首页,你会发现它现在显示的是
list_index.htm的内容,并且带有分页功能。
这种方法的缺点:
- 破坏核心文件:直接修改
index.php,升级DedeCMS时这些修改会被覆盖。 - 逻辑混乱:首页和列表页的模板逻辑混在一起,不易维护。
- 性能问题:每次访问首页都会执行和列表页一样的复杂查询,性能可能不如方法一。
| 特性 | 方法一 (自定义SQL+标签) | 方法二 (修改核心文件) |
|---|---|---|
| 推荐度 | ⭐⭐⭐⭐⭐ (强烈推荐) | ⭐ (不推荐) |
| 灵活性 | 非常高,可以自定义任何SQL查询 | 较低,受限于列表页逻辑 |
| 性能 | 好,只查询需要的数据 | 一般,执行完整列表查询 |
| 维护性 | 优秀,代码与模板分离,不破坏核心 | 差,修改核心文件,升级困难 |
| 安全性 | 高,SQL语句可控 | 较低,需小心处理全局变量 |
| 实现复杂度 | 中等,需要写一点PHP代码 | 简单,只需修改配置文件 |
对于任何新项目或希望长期维护的网站,请务必选择方法一,它更符合现代CMS的开发理念,也更稳定、高效。
