dede搜索页分页怎么实现?

99ANYc3cd6
预计阅读时长 32 分钟
位置: 首页 DEDE建站 正文

这个问题非常经典,因为 DedeCMS 的搜索页 search.php 默认的分页逻辑与列表页 list.php 是不同的,它不依赖于 arc.listview.class.php 这个文件,而是有自己的处理方式。

实现 DedeCMS 搜索分页主要分为两个步骤:

  1. 修改搜索页模板 search.htm:在模板中添加分页的代码标签。
  2. 修改搜索处理文件 search.php:在后台处理分页参数并传递给模板。

第一步:修改搜索页模板 search.htm

在您的搜索页模板文件中,您需要找到您希望显示分页的位置,然后插入 DedeCMS 的分页标签。

常用分页标签如下:

  1. {dede:pagelist listitem="index,end,pre,next,pageno" listsize="5"}

    • 这是最常用的分页标签,它会显示一个包含首页、末页、上一页、下一页和页码的导航栏。
    • listitem:定义要显示的项,index是首页,end是末页,pre是上一页,next是下一页,pageno是当前页码。
    • listsize:显示的页码数量,5 表示当前页码左右各显示 2 个页码。
  2. {dede:pagelist listitem="index,end,pre,next"}

    这个标签只显示首页、末页、上一页、下一页,不显示具体的页码列表。

  3. {dede:pagelist listitem="pageno"}

    这个标签只显示页码列表。

示例 search.htm 代码:

假设您的搜索结果列表循环代码是 {dede:arclist},那么您可以在列表循环结束后添加分页标签。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">搜索结果</title>
</head>
<body>
    <h1>搜索结果</h1>
    <!-- 搜索表单 -->
    <form name="formsearch" action="{dede:global.cfg_cmspath/}/search.php">
        <input type="hidden" name="kwtype" value="0" />
        <input type="text" name="q" id="q" value="{dede:global name='q'/}" />
        <button type="submit">搜索</button>
    </form>
    <hr>
    <!-- 搜索结果列表 -->
    {dede:arclist titlelen='40' row='10'}
    <li>
        <a href="[field:arcurl/]">[field:title/]</a>
        <p>[field:description function='cn_substr(@me,100)'/]...</p>
    </li>
    {/dede:arclist}
    <!-- 分页导航代码 -->
    <div class="dede_pages">
        <ul class="pagelist">
            {dede:pagelist listitem="index,end,pre,next,pageno" listsize="5"}
        </ul>
    </div>
</body>
</html>

注意:

  • {dede:arclist} 中的 row='10' 表示每页显示 10 条结果,这个值与 search.php 中的 pagesize 变量相对应。
  • {dede:global name='q'/} 用于在搜索框中回显用户输入的关键词。

第二步:修改搜索处理文件 search.php

这是最关键的一步。search.php 文件负责接收搜索请求,从数据库中查询数据,然后调用 search.htm 模板并传递数据,我们需要修改它来支持分页。

请打开您的 search.php 文件,找到类似下面的代码块(通常在文件末尾):

//搜索结果分页
$pageno = isset($pageno) && is_numeric($pageno) ? intval($pageno) : 1;
$PageSize = 10; //每页显示多少条
$totalresult = $dsql->GetOne("SELECT COUNT(*) AS dd FROM `dede_archives` WHERE {$orwhere}");
$totalresult = $totalresult['dd'];
$totalpage = ceil($totalresult / $PageSize);
$limitstart = ($pageno - 1) * $PageSize;
$orderby = "id DESC";
$orwhere = " (title like '%$q%' OR body like '%$q%') ";
//执行查询
$query = "SELECT * FROM `dede_archives` WHERE {$orwhere} ORDER BY $orderby LIMIT $limitstart,$PageSize";
$rslist = '';
$dsql->SetQuery($query);
$dsql->Execute();
while($arr = $dsql->GetArray())
{
    $rslist .= GetArcList($arr, $typeid, $innertext, $arcid, $flag, $ismake, $channelid, $imgwidth, $imgheight, $page, $order, $subday, $noself, $aid, $titlelen);
}

代码可能存在以下问题,需要进行优化和修正:

  1. $dsql->SetQueryExecute:直接执行 SetQueryExecute 是不推荐的,应该使用 dsql 对象的 Select() 方法,它更安全、更高效。
  2. GetArcList 函数:这个函数通常用于列表页,用于处理分页标签等复杂逻辑,在搜索页直接用它来循环数据可能会导致分页标签无法正常工作,更简单的方式是直接获取文章的基本信息并输出。

优化后的 search.php 关键代码:

请用以下代码替换掉 search.php 中处理分页和查询的部分。

// --- 开始替换 ---
// 1. 接收并处理分页参数
$pageno = isset($pageno) && is_numeric($pageno) ? intval($pageno) : 1;
$PageSize = 10; // 每页显示条数,请根据需要修改
// 2. 构建搜索条件 (注意:为了安全,建议对 $q 进行转义)
$q = addslashes($q); // 防止SQL注入
$orwhere = " (title like '%$q%' OR body like '%$q%') ";
// 3. 获取总记录数
$totalresult = $dsql->GetOne("SELECT COUNT(*) AS dd FROM `#@__archives` WHERE {$orwhere}");
$totalresult = $totalresult['dd'];
$totalpage = ceil($totalresult / $PageSize);
// 4. 计算当前页的偏移量
if($pageno > $totalpage) $pageno = $totalpage;
if($pageno < 1) $pageno = 1;
$limitstart = ($pageno - 1) * $PageSize;
// 5. 执行查询,获取当前页的数据
$query = "SELECT * FROM `#@__archives` WHERE {$orwhere} ORDER BY id DESC LIMIT $limitstart, $PageSize";
$rslist = '';
$dsql->Execute('al',$query); // 使用 'al' 作为别名,避免冲突
// 6. 循环处理查询结果,并生成列表HTML
while($arr = $dsql->GetArray('al'))
{
    // 这里我们直接获取文章信息并拼接,也可以调用 {dede:arclist} 的相关逻辑,但直接拼接更简单直接
    $arcurl = GetFileUrl($arr['id'], $arr['typeid'], $arr['senddate'], $arr['title'], $arr['ismake'], $arr['arcrank'], $arr['namerule'], $arr['typedir'], $arr['money'], $arr['filename'], $arr['moresite'], $arr['siteurl'], $arr['sitepath']);
    $rslist .= "<li>\n";
    $rslist .= "    <a href='{$arcurl}' target='_blank'>".cn_substr($arr['title'], 40)."</a>\n";
    $rslist .= "    <p>".cn_substr(preg_replace('/<[^>]*>/', '', $arr['description']), 100)."...</p>\n";
    $rslist .= "</li>\n";
}
// 7. 将必要的数据传递给模板
$parseTag = new DedeTagParse();
$parseTag->SetNameSpace('field', '[', ']');
$parseTag->LoadString($innertext);
$parseTag->SetVar('item', $rslist); // 将生成的列表HTML传递给模板的 [field:item] 标签
$parseTag->SetVar('totalresult', $totalresult); // 总结果数
$parseTag->SetVar('totalpage', $totalpage);    // 总页数
$parseTag->SetVar('pageno', $pageno);          // 当前页码
$parseTag->ParseDT();
// 将分页数据也传递给模板,供 {dede:pagelist} 使用
$dpages = '';
$dpages .= "<div class=\"dede_pages\">\n";
$dpages .= "<ul class=\"pagelist\">\n";
$prepage = ($pageno > 1) ? "<li><a href=\"search.php?q=".urlencode($q)."&pageno=".($pageno-1)."\">上一页</a></li>" : "";
$nextpage = ($pageno < $totalpage) ? "<li><a href=\"search.php?q=".urlencode($q)."&pageno=".($pageno+1)."\">下一页</a></li>" : "";
$dpages .= $prepage.$nextpage; // 这里简化处理,实际项目中应使用 {dede:pagelist} 标签
$dpages .= "</ul>\n";
$dpages .= "</div>\n";
$parseTag->SetVar('pagelist', $dpages);
// --- 结束替换 ---
// 引入模板文件
include(DEDETEMPLATE.'/search.htm');

对上述 search.php 修改的说明:

  1. 安全处理:使用 addslashes($q) 对搜索关键词进行简单的转义,防止 SQL 注入。
  2. 获取总记录数$dsql->GetOne 获取符合条件的文章总数,用于计算总页数。
  3. 计算偏移量$limitstart 是 SQL LIMIT 子句中第二个参数的值,用于定位到当前页的数据。
  4. 执行查询$dsql->Execute('al', $query) 执行带分页的查询。'al' 是一个查询别名,避免与其他查询冲突。
  5. 生成列表:循环查询结果,使用 GetFileUrl 获取文章链接,并用 cn_substr 截取标题和描述,最终拼接成 HTML 字符串 $rslist
  6. 传递数据:这部分是核心,我们创建了一个 DedeTagParse 对象,将生成的 $rslist$totalresult 等变量传递给模板,这样,您在 search.htm 中就可以通过 [field:item] 来显示列表,[field:totalresult] 来显示总数。
  7. {dede:pagelist} 的工作原理{dede:pagelist} 标签会自动寻找 search.php 传递过来的 pagenototalpage 等变量,并生成相应的分页链接,您只需要在模板中放置标签即可,search.php 中不需要手动生成 <a> 标签(虽然上面的代码也手动生成了作为示例,但实际项目中应完全依赖模板标签)。

更简单、推荐的方法(仅修改模板)

如果你的 DedeCMS 版本较新(如 5.7+),并且你的搜索需求比较简单(只搜索文章标题),那么你可能只需要修改模板,而完全不需要修改 search.php

前提条件:

  • 你没有修改过 search.php 文件。
  • 你的搜索范围仅限于 #@__archives 表(即文章)。

操作步骤:

  1. 确保 search.php 中的查询逻辑正确,默认的 search.php 代码已经包含了分页逻辑,只是可能没有在模板中调用分页标签。

  2. 修改 search.htm 模板,将你的列表循环和分页标签改成下面这样:

    {dede:global name='keyword' function='RemoveXSS(@me)'/}  <!-- 安全输出关键词 -->
    <div>共找到 <strong>[field:totalrecord/]</strong> 条结果</div>
    <!-- 使用 {dede:list} 标签来循环搜索结果,这是最关键的一步! -->
    {dede:list pagesize='10'}
    <li>
        <a href="[field:arcurl/]">[field:title/]</a>
        <span>[field:pubdate function='MyDate("Y-m-d",@me)'/]</span>
        <p>[field:description function='cn_substr(@me,200)'/]...</p>
    </li>
    {/dede:list}
    <!-- 分页标签,直接放在 {dede:list} 循环后面 -->
    <div class="dede_pages">
        <ul class="pagelist">
            {dede:pagelist listitem="index,end,pre,next,pageno" listsize="5"}
        </ul>
    </div>

为什么这个方法可行?

因为 DedeCMS 的 search.php 在检测到模板中使用了 {dede:list} 标签时,会自动切换到列表模式,并自动处理分页逻辑,将 totalpage, pageno 等变量传递给模板,{dede:pagelist} 标签就能正常工作了。

  • 首选方法:尝试仅修改 search.htm 模板,使用 {dede:list} 标签,这是最安全、最简单、最符合 DedeCMS 设计思想的方法。
  • 备用方法:如果搜索逻辑非常复杂(例如需要联合多个表查询),或者默认的 search.php 已被修改得面目全非,那么才需要按照第二步的方法,手动修改 search.php 文件,并自己构建列表和传递分页数据。

希望这个详细的教程能帮到您!

-- 展开阅读全文 --
头像
dede数据库配置文件在哪?如何正确配置?
« 上一篇 05-06
C语言中pow函数是什么意思?
下一篇 » 05-06

相关文章

取消
微信二维码
支付宝二维码

目录[+]