
本文介绍如何在 yii2 控制器中安全、规范地接收前端传入的产品、月份和年份参数,动态构建 sql 查询并返回 json 响应,涵盖参数绑定、查询优化与 yii 原生 json 格式支持。
在 Yii2 中实现基于下拉框(product / month / year)的前端数据筛选,关键在于安全接收参数、防止 SQL 注入、合理组织查询逻辑,并利用框架原生能力简化响应处理。以下为完整、可落地的实践方案:
✅ 1. 定义带参数的动作方法(Action)
将筛选条件作为动作方法的参数,Yii2 会自动从 GET/POST 请求中解析(支持 URL 路由或表单提交):
public function actionProducts($product = null, $month = null, $year = null) { // 构建基础查询条件(允许部分条件为空,实现灵活筛选) $conditions = []; $params = []; if (!empty($year)) { $conditions[] = 'year = :year'; $params[':year'] = (int)$year; // 强制转为整型,增强安全性 } if (!empty($month)) { $conditions[] = 'month = :month'; $params[':month'] = $month; } if (!empty($product)) { $conditions[] = 'product = :product'; $params[':product'] = $product; } $whereClause = !empty($conditions) ? 'WHERE ' . implode(' AND ', $conditions) : ''; $sql = "SELECT product, cost, supplier, month, year FROM products {$whereClause} GROUP BY product, month, year"; $data = Data::findBySql($sql, $params)->asArray()->all(); Yii::$app->response->format = yiiwebResponse::FORMAT_JSON; return ['data' => $data]; }
? 说明: 使用 NULL 默认值支持可选筛选(如仅按年份查询); 对 $year 显式 (int) 类型转换,避免字符串注入风险; 动态拼接 WHERE 条件,避免硬编码冗余条件(原答案中 WHERE … AND year=:year 重复书写有误,已修正)。
✅ 2. 推荐进阶:改用 ActiveRecord 查询(更安全、更 Yii 风格)
相比原生 SQL,ActiveRecord 提供更好的可维护性与 ORM 安全保障:
public function actionProducts($product = null, $month = null, $year = null) { $query = Data::find() ->select(['product', 'cost', 'supplier', 'month', 'year']) ->groupBy(['product', 'month', 'year']); if (!empty($year)) { $query->andWhere(['year' => (int)$year]); } if (!empty($month)) { $query->andWhere(['month' => $month]); } if (!empty($product)) { $query->andWhere(['product' => $product]); } $data = $query->asArray()->all(); Yii::$app->response->format = yiiwebResponse::FORMAT_JSON; return ['data' => $data]; }
✅ 优势:自动参数绑定、SQL 注入免疫、支持缓存与关系查询扩展。
立即学习“前端免费学习笔记(深入)”;
✅ 3. 前端调用示例(ajax)
确保前端通过 GET 或 POST 正确传递参数(如使用 jquery):
$.get('/site/products', { product: $('#product-select').val(), month: $('#month-select').val(), year: $('#year-select').val() }, function(res) { console.log(res.data); // 渲染表格或图表... });
⚠️ 注意事项
- 路由配置:若使用美化 URL(如 /products?year=2022&month=12),无需额外配置;若需 /products/2022/12 形式,需在 urlManager 中定义规则。
- 空值处理:$product = null 等默认值确保无参请求不报错;实际业务中建议对空参数做逻辑兜底(如返回全部数据或提示“请选择筛选项”)。
- 性能提醒:GROUP BY 在大数据量下可能影响性能,建议为 year、month、product 字段建立联合索引。
- 响应头无需手动设置:Yii 的 FORMAT_jsON 会自动设置 Content-Type: application/json 及正确编码,删除原代码中冗余的 header() 和 json_encode() 手动调用。
通过以上方式,你就能构建一个安全、灵活、符合 Yii2 最佳实践的数据筛选接口,为前端提供稳定可靠的动态数据服务。