
本文讲解如何在 CodeIgniter 中正确展示一本图书对应多个作者的情况,解决因 GROUP BY 导致仅显示单个作者的问题,核心方案是使用 GROUP_CONCAT 聚合作者姓名,并强调 XSS 防护等关键实践。
本文讲解如何在 codeigniter 中正确展示一本图书对应多个作者的情况,解决因 `group by` 导致仅显示单个作者的问题,核心方案是使用 `group_concat` 聚合作者姓名,并强调 xss 防护等关键实践。
在构建电子图书馆(E-Library)系统时,一个常见需求是:每本书可能由多位作者共同撰写(如《Design Patterns》有 Gamma、Helm、Johnson、Vlissides 四位作者),但默认的 JOIN + GROUP BY 查询会因 MySQL 分组机制只保留一条作者记录,导致视图中始终只显示“第一位作者”(如仅显示 “Tom” 而遗漏 “Jerry”)。
根本原因在于:当对 tbl_authors.book_id 执行 GROUP BY 时,MySQL 在未明确聚合规则的情况下,会任意选取该分组中某一行的 author_name 值(通常为第一条匹配记录),而非合并全部作者。因此,不能依赖 SELECT * 加简单分组,而应主动聚合作者字段。
✅ 正确做法:使用 GROUP_CONCAT() 函数将同一本书的所有作者姓名拼接为逗号分隔的字符串。CodeIgniter 的 Query Builder 支持原生 SQL 表达式,可安全嵌入:
public function getbooks()
{
return $this->db->select("tbl_books.*,
tbl_section.section_name,
GROUP_CONCAT(tbl_authors.author_name SEPARATOR ', ') AS author_names")
->from('tbl_books')
->join('tbl_section', 'tbl_books.section_id = tbl_section.section_id')
->join('tbl_authors', 'tbl_books.book_id = tbl_authors.book_id')
->group_by('tbl_books.book_id') // ✅ 关键:按图书分组,而非作者表字段
->get()
->result_array();
}⚠️ 注意事项:
- 分组字段必须是主表唯一标识:应使用 tbl_books.book_id(确保每本书一行),而非 tbl_authors.book_id(逻辑等价但语义不清);
- 显式指定所需字段:避免 SELECT * 与 GROUP_CONCAT 混用引发的 SQL 模式兼容性问题(如 ONLY_FULL_GROUP_BY 启用时会报错);
- 字符集与长度限制:GROUP_CONCAT 默认最大长度为 1024 字符,若作者名过长或数量过多,需在查询前设置:$this->db->query("SET SESSION group_concat_max_len = 10000");;
- 空作者处理:若某书暂无作者记录,author_names 将为 NULL,建议在视图中做空值判断。
在视图中,直接输出聚合后的字段,并务必进行 HTML 实体转义以防止 XSS 攻击:
<td class="center">
<?php echo htmlspecialchars($value['author_names'] ?? '未知作者', ENT_QUOTES, 'UTF-8'); ?>
</td>? 进阶建议:
如需支持作者链接、排序或分页优化,可考虑改用子查询或预加载模式(如先查图书列表,再批量查询对应作者),但对中等规模数据(










