You need to enable JavaScript to run this app. CodeIgniter 4 如何用构建器或原生查询获取当前条目前后相邻行
优惠活动
大模型
产品
解决方案
定价
更多

CodeIgniter 4 如何用构建器或原生查询获取当前条目前后相邻行

代码修正与功能实现方案

基础问题修正

原代码存在两个直接影响运行的问题:

  • 未初始化$builder实例,未绑定查询主表,直接调用会触发未定义类的报错
  • 直接将传入参数$qs拼接到SQL语句中,存在SQL注入风险

功能实现逻辑

要拿到目标条目的相邻关联数据,核心是先通过目标ID定位排序锚点(基于segments_en的自增主键作为稳定排序依据,避免顺序错乱),再按同归属的tape字段圈定范围,拉取锚点前后指定数量的记录即可。

CodeIgniter4 查询构建器实现版本

可直接运行的修正后代码如下:

public function show_questions($qs = false)
{
    $db = \Config\Database::connect();
    // 参数有效性校验
    if (!$qs || !is_numeric($qs)) {
        return [];
    }
    // 初始化绑定questions_en表的查询构建器
    $builder = $db->table('questions_en');
    // 第一步:定位目标条目的锚点值
    $anchor = $builder->select('questions_en.tape, segments_en.segment_id')
        ->join('segments_en', 'questions_en.tape = segments_en.tape')
        ->where('questions_en.question_id', $qs)
        ->get()
        ->getRowArray();
    // 目标条目不存在直接返回空数组
    if (!$anchor) {
        return [];
    }
    // 第二步:拉取锚点前后各3条同tape的关联记录
    $neighborList = $builder->select('*')
        ->join('segments_en', 'questions_en.tape = segments_en.tape')
        ->where('segments_en.tape', $anchor['tape'])
        // 调整以下两个边界值即可灵活控制前后取数的条数,比如前2后3就把-3改成-2
        ->where('segments_en.segment_id >=', $anchor['segment_id'] - 3)
        ->where('segments_en.segment_id <=', $anchor['segment_id'] + 3)
        ->orderBy('segments_en.segment_id', 'ASC');
    return $neighborList->get()->getResultArray();
}

原生查询实现版本

如果偏好原生SQL写法,可使用CI4支持的参数绑定原生查询逻辑:

public function show_questions($qs = false)
{
    $db = \Config\Database::connect();
    if (!$qs || !is_numeric($qs)) {
        return [];
    }
    // 先查出锚点值,计算范围边界
    $anchor = $db->query(
        "SELECT s2.segment_id FROM questions_en q2 JOIN segments_en s2 ON q2.tape = s2.tape WHERE q2.question_id = ? LIMIT 1",
        [$qs]
    )->getRowArray();
    if (!$anchor) {
        return [];
    }
    $sql = "
        SELECT * 
        FROM questions_en q
        JOIN segments_en s ON q.tape = s.tape
        WHERE q.tape = (
            SELECT q2.tape 
            FROM questions_en q2
            JOIN segments_en s2 ON q2.tape = s2.tape
            WHERE q2.question_id = ?
            LIMIT 1
        )
        AND s.segment_id BETWEEN ? AND ?
        ORDER BY s.segment_id ASC
    ";
    $startId = $anchor['segment_id'] - 3;
    $endId = $anchor['segment_id'] + 3;
    return $db->query($sql, [$qs, $startId, $endId])->getResultArray();
}

实现说明

  • 返回结果天然包含目标条目本身,前后各覆盖最多3条相邻记录;如果靠前/靠后方向没有足够的记录,会自动返回实际存在的条目,不需要额外的空值兼容逻辑
  • 调整两个边界计算的数值,即可灵活实现“前2条后3条”这类差异化取数需求
  • 生产环境建议给segments_en表加(tape, segment_id)的联合索引,大范围查询时性能会有明显提升

内容的提问来源于stack exchange,提问作者AviR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.07 17:06:00