
本文介绍如何在 yii2 控制器中安全、规范地接收前端传入的产品、月份和年份参数,动态构建 sql 查询并返回 json 格式响应,涵盖参数绑定、查询优化与响应格式设置等关键实践。
在 Yii2 中实现基于下拉框(product / month / year)的前端数据筛选,核心在于安全接收参数、正确构造查询条件、避免 SQL 注入,并遵循框架推荐的响应方式。以下为完整、可落地的实现方案:
✅ 正确声明动作参数并构建查询
将筛选字段作为动作方法的参数显式声明,Yii2 会自动从 GET/POST 请求中解析(支持路由参数或查询字符串),提升可读性与类型安全性:
public function actionProducts($product = null, $month = null, $year = null)
{
// 构建基础查询:使用参数化占位符防止 SQL 注入
$sql = "SELECT product, cost, supplier, month, year
FROM products
WHERE 1=1";
$params = [];
if (!empty($year)) {
$sql .= " AND year = :year";
$params[':year'] = (int)$year; // 强制转为整型,增强健壮性
}
if (!empty($month)) {
$sql .= " AND month = :month";
$params[':month'] = $month;
}
if (!empty($product)) {
$sql .= " AND product = :product";
$params[':product'] = $product;
}
$sql .= " GROUP BY product, month, year";
$data = Data::findBySql($sql, $params)->asArray()->all();
// ✅ 使用 Yii2 内置 JSON 响应机制(推荐)
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
return ['data' => $data];
}⚠️ 注意事项与最佳实践
- 不要手动 header() + json_encode():这会绕过 Yii2 的响应生命周期,导致缓存、内容协商、CORS 等功能失效;
- 参数校验不可省略:生产环境建议结合 yii\validators 或手动验证(如 $year 是否为合法年份);
- 避免重复条件:原示例中 WHERE year = :year AND month=:month AND year=:year 存在冗余,已修正;
-
考虑使用 ActiveRecord 替代原生 SQL(更安全、可测试):
$query = Data::find() ->select(['product', 'cost', 'supplier', 'month', 'year']) ->andFilterWhere(['year' => $year]) ->andFilterWhere(['month' => $month]) ->andFilterWhere(['product' => $product]) ->groupBy(['product', 'month', 'year']); $data = $query->asArray()->all();
? 前端调用示例(AJAX)
fetch('/site/products?product=ABC&month=05&year=2024')
.then(res => res.json())
.then(data => console.log(data.data));通过以上方式,你既能保持代码清晰可维护,又能充分利用 Yii2 的安全机制与响应管理能力,为后续扩展(如分页、排序、导出)打下坚实基础。










