dede sql如何正确调用栏目信息?

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

下面我将从基础语法常用场景安全注意事项三个方面,为你详细讲解如何使用 SQL 调用栏目。

dede sql 调用栏目
(图片来源网络,侵删)

基础语法

在 DedeCMS 模板中,使用 SQL 调用主要通过 {dede:sql} 标签实现,其基本结构如下:

{dede:sql sql='你的SQL语句'}
    <!-- 循环体,使用[field:字段名/]来输出数据 -->
    <a href="[field:typedir/]">[field:typename/]</a>
{/dede:sql}

核心参数说明:

  • sql='...': 这是必需的参数,用于填写你的 SQL 查询语句。
  • itemindex='数字': 可选,用于给循环体中的变量命名前缀,itemindex='my',那么字段名就变成了 [field:my.name/],在多表查询、字段名可能冲突时非常有用。
  • islocal='yes': 可选,设置为 yes 时,可以将查询结果缓存到本地,提高页面加载速度,但对于栏目列表这类不常变动的数据,可以开启。

常用场景与示例

DedeCMS 的栏目信息主要存储在 dede_arctype 表中,我们的 SQL 查询主要围绕这张表进行。

场景1:获取指定ID的栏目信息

如果你想获取某一个特定栏目的详细信息(比如栏目名称、链接等),可以直接查询 dede_arctype 表。

dede sql 调用栏目
(图片来源网络,侵删)

示例:获取栏目ID为 1 的栏目信息

{dede:sql sql='SELECT id, typename, typedir, description FROM dede_arctype WHERE id = 1'}
    <h2>[field:typename/]</h2>
    <p>栏目链接:<a href="[field:typedir/]">[field:typename/]</a></p>
    <p>栏目描述:[field:description function="htmlspecialchars(@me)"/]</p>
{/dede:sql}

代码解析:

  • SELECT id, typename, typedir, description FROM dede_arctype WHERE id = 1:查询 dede_arctype 表,获取 id1 的栏目的 idtypename(栏目名)、typedir(栏目链接)、description(栏目描述)。
  • [field:typename/]:输出栏目名称。
  • [field:typedir/]:输出栏目链接,通常需要加上你的网站域名。
  • function="htmlspecialchars(@me)":对输出内容进行 HTML 转义,防止 XSS 攻击,是一个良好的安全习惯。

场景2:获取指定层级的所有栏目

获取所有顶级栏目(topid0 的栏目)。

示例:获取所有顶级栏目

dede sql 调用栏目
(图片来源网络,侵删)
<ul>
    {dede:sql sql='SELECT id, typename, typedir FROM dede_arctype WHERE topid = 0 ORDER BY sortrank ASC'}
        <li><a href="[field:typedir/]">[field:typename/]</a></li>
    {/dede:sql}
</ul>

代码解析:

  • WHERE topid = 0:这是关键条件,topid 字段表示栏目的父级栏目ID,0 代表顶级。
  • ORDER BY sortrank ASC:按照 sortrank(排序权重)字段进行升序排列,确保栏目按你设定的顺序显示。

场景3:获取指定栏目的所有子栏目

获取栏目ID为 5 的所有直接子栏目。

示例:获取栏目ID为 5 的所有子栏目

<ul>
    {dede:sql sql='SELECT id, typename, typedir FROM dede_arctype WHERE reid = 5 ORDER BY sortrank ASC'}
        <li><a href="[field:typedir/]">[field:typename/]</a></li>
    {/dede:sql}
</ul>

代码解析:

  • WHERE reid = 5reid 字段表示栏目的父级栏目ID,这个条件用于筛选出父级栏目ID为 5 的所有子栏目。

场景4:获取指定栏目及其所有子栏目(递归查询)

这是一个比较复杂的需求,因为 SQL 本身不支持递归查询(除非使用特定数据库的递归语法),在 DedeCMS 中,我们通常利用系统内置的函数来实现。

示例:获取当前栏目及其所有子栏目(推荐方法)

{dede:channel type='son' currentstyle='
    <li class="current"><a href~typename~</a></li>
    '}
    <li><a href='[field:typedir/]'>[field:typename/]</a></li>
{/dede:channel}

为什么推荐这个方法?

  • {dede:channel} 是 DedeCMS 专门为栏目调用设计的标签,它内部已经处理了递归逻辑,性能更好,代码更简洁。
  • type='son' 表示调用当前栏目的子栏目。
  • currentstyle 用于高亮显示当前栏目。

如果必须用 SQL 实现(不推荐) 你需要先通过 PHP 获取所有子栏目的 ID,然后再拼凑 SQL 查询,这非常麻烦且容易出错,因此强烈建议优先使用 {dede:channel}


场景5:跨表查询(获取栏目及其文章数)

这是一个非常实用的场景,例如在首页制作一个热门栏目列表,显示每个栏目下的文章数量。

这需要同时查询 dede_arctype(栏目表)和 dede_archives(文章表)。

示例:获取顶级栏目及其对应的文章总数

<ul>
    {dede:sql sql='SELECT a.id, a.typename, a.typedir, COUNT(b.id) as article_count FROM dede_arctype as a LEFT JOIN dede_archives as b ON a.id = b.typeid WHERE a.topid = 0 GROUP BY a.id ORDER BY a.sortrank ASC'}
        <li>
            <a href="[field:typedir/]">[field:typename/]</a>
            (文章数: [field:article_count/])
        </li>
    {/dede:sql}
</ul>

代码解析:

  • SELECT a.id, a.typename, ...:给 dede_arctype 表起一个别名 a,方便引用。
  • FROM dede_arctype as a LEFT JOIN dede_archives as b ON a.id = b.typeid:将 dede_arctype 表(别名为 a)和 dede_archives 表(别名为 b)进行左连接,连接条件是栏目的 id 等于文章的 typeid
  • COUNT(b.id) as article_count:对每个栏目分组后,统计 b.id(即文章ID)的数量,并将结果命名为 article_count
  • GROUP BY a.id:按栏目ID进行分组,这是 COUNT 聚合函数所必需的。
  • [field:article_count/]:输出计算出的文章总数。

安全注意事项

直接在模板中写 SQL 存在巨大的安全风险,最常见的就是 SQL 注入,攻击者可以通过修改 URL 参数来恶意的拼接 SQL 语句,从而窃取、修改甚至删除你的数据库数据。

如何防范?

  1. 永远不要直接使用外部变量 绝对不要将 URL 中的 GET 参数直接拼接到 SQL 语句中。

    错误示范(高危!)

    {dede:sql sql='SELECT * FROM dede_arctype WHERE id = ~id~'}

    URL 是 ...?id=1 OR 1=1,SQL 就会被篡改。

  2. 使用 DedeCMS 内置的 GetOneExecute 函数(高级用法) 在更复杂的情况下,你可以在PHP文件中进行数据库查询,而不是在模板里,PHP 文件中的查询可以更好地进行参数过滤。

    示例(在 plus/my_list.php 文件中)

    <?php
    require_once(dirname(__FILE__)."/../include/common.inc.php");
    // 安全地获取ID参数
    $id = isset($id) && is_numeric($id) ? intval($id) : 0;
    if($id > 0) {
        $query = "SELECT * FROM dede_arctype WHERE id = $id";
        $row = $dsql->GetOne($query); // 使用DedeCMS的数据库对象进行查询
        if(is_array($row)) {
            // 将查询结果赋值给模板
            $GLOBALS['typeinfo'] = $row;
        }
    }
    // 引入模板文件
    include(DEDETEMPLATE.'/plus/my_list.htm');
    ?>

    模板文件 (my_list.htm)

    {dede:getdata name='typeinfo'}
        <h2>[field:typename/]</h2>
    {/dede:getdata}

    这种方式通过 intval()is_numeric() 对输入参数进行了严格的类型检查,从根本上杜绝了 SQL 注入。

场景 推荐标签/方法 备注
获取单个栏目 {dede:sql} 简单直接,注意SQL注入风险。
获取顶级/子栏目列表 {dede:channel} 强烈推荐,系统自带,功能强大,性能好。
递归查询栏目 {dede:channel} 内置支持,无需手动写复杂SQL。
跨表查询(如栏目文章数) {dede:sql} 功能灵活,但SQL语句较复杂,需注意安全。
复杂动态查询 PHP文件 + {dede:sql}{dede:getdata} 最安全、最灵活的方式,适合开发复杂模块。

对于大多数常规的栏目调用需求,优先使用 {dede:channel} 标签,只有在它无法满足的特殊需求下,才谨慎使用 {dede:sql},并务必牢记安全第一,杜绝SQL注入。

-- 展开阅读全文 --
头像
C语言程序设计第三版谭浩强核心内容是什么?
« 上一篇 今天
中英文企业网站织梦猫
下一篇 » 今天

相关文章

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

目录[+]