
本文介绍如何在 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 = \yii\web\Response::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 = \yii\web\Response::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 最佳实践的数据筛选接口,为前端提供稳定可靠的动态数据服务。










