
通过一条 sql 查询获取全部菜单类型(starter、main_course、deserts、drinks)的数据,并在 php 层按 type 动态分组,可显著减少数据库往返次数,提升页面加载性能。
通过一条 sql 查询获取全部菜单类型(starter、main_course、deserts、drinks)的数据,并在 php 层按 type 动态分组,可显著减少数据库往返次数,提升页面加载性能。
在 CodeIgniter 3 开发中,频繁执行结构相似的 SQL 查询(如按不同 type 值筛选同一张表)是典型的性能瓶颈。您当前的代码执行了 4 次独立查询,不仅增加数据库连接开销,还导致多次结果集解析和内存分配。优化核心在于:用一次查询获取全量数据,再在应用层完成逻辑分组。
✅ 推荐解决方案如下:
// 替换原有的 4 次查询为以下单条查询
$getMenus = $this->db->query(
"SELECT * FROM table_name
WHERE status = '1'
AND type IN ('starter', 'main_course', 'deserts', 'drinks')
ORDER BY id DESC"
);
$allMenus = $getMenus->result_array();
// 初始化空数组,用于动态构建分类键
$data = [];
// 遍历结果,按 type 字段自动归类到对应键名(如 'all_starter_menu')
foreach ($allMenus as $menu) {
// 构造键名:all_{type}_menu → 将下划线移除以匹配原视图变量命名习惯(如 'starter' → 'all_starter_menu')
$key = 'all_' . str_replace('_', '', $menu['type']) . '_menu';
$data[$key][] = $menu;
}
// 可选:确保所有预期键都存在(避免视图中未定义变量报错)
$expected_types = ['starter', 'main_course', 'deserts', 'drinks'];
foreach ($expected_types as $type) {
$key = 'all_' . str_replace('_', '', $type) . '_menu';
if (!isset($data[$key])) {
$data[$key] = [];
}
}
? 关键说明与注意事项:
- ✅ SQL 层优化:
WHERE ... AND type IN (...)利用索引(建议为(status, type)建复合索引)可大幅提升查询效率;若type取值固定且唯一,甚至可省略IN条件,仅保留status = '1'。 - ✅ PHP 层分组:使用
str_replace('_', '', $menu['type'])是为兼容您原始视图中$all_starter_menu这类变量名(即starter→all_starter_menu),若实际视图已接受all_main_course_menu(带下划线),请改为'all_' . $menu['type'] . '_menu'。 - ⚠️ 字段一致性:确保
table_name中type字段值严格等于'starter'/'main_course'等字符串(区分大小写),否则分组会遗漏数据。 - ? 扩展性提示:未来新增菜单类型(如
'appetizer')时,只需在IN子句和$expected_types数组中同步添加,无需修改循环逻辑。
最终,您的视图代码完全无需改动——$all_starter_menu、$all_maincourse_menu 等变量仍可照常使用,但页面加载速度将明显提升。这种「查询聚合 + 应用层分组」模式,是 CodeIgniter 及多数 PHP 框架中优化 N+1 查询问题的经典实践。











