
本文介绍如何在 yii2 框架中通过控制器接收产品、月份、年份等前端筛选参数,并安全、高效地执行 sql 查询与 json 响应返回,涵盖参数绑定、sql 防注入及标准 json 格式化实践。
在 Yii2 中实现动态数据筛选,关键在于安全接收请求参数、构建可扩展的查询逻辑、规范返回 JSON 响应。你当前的代码存在几个典型问题:硬编码年份(2022)、WHERE 条件重复(year = :year 出现两次)、未使用 Yii 内置响应机制,且缺少对空值或非法参数的容错处理。
✅ 正确做法:参数化 + 响应格式化
首先,将筛选条件作为动作方法参数显式声明,Yii2 会自动从 GET/POST 请求中解析(支持 URL 路由和表单提交):
<?php
public function actionProducts($product = null, $month = null, $year = null)
{
// 构建动态 WHERE 条件
$conditions = [];
$params = [];
if (!empty($year)) {
$conditions[] = 'year = :year';
$params[':year'] = (int)$year;
}
if (!empty($month)) {
$conditions[] = 'month = :month';
$params[':month'] = (int)$month;
}
if (!empty($product)) {
$conditions[] = 'product = :product';
$params[':product'] = trim($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();
// 使用 Yii2 原生 JSON 响应(自动设置 Content-Type、处理编码、支持 JSON_NUMERIC_CHECK)
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
return ['data' => $data];
}⚠️ 注意事项与最佳实践
- SQL 安全性:始终使用命名参数(如 :year)并绑定值,杜绝字符串拼接,防止 SQL 注入;
- 参数健壮性:为参数设置默认值(如 $year = null),并做类型转换与空值判断,避免查询异常;
- GROUP BY 合理性:若需按产品汇总成本,建议明确聚合逻辑(如 SUM(cost)),当前 SELECT * ... GROUP BY 在严格 SQL 模式下可能报错;
-
前端调用示例(GET 请求):
/index.php?r=your-controller/products&year=2023&month=5&product=WidgetA - 性能提示:为 year、month、product 字段建立联合索引(如 INDEX idx_filter (year, month, product))可显著提升查询效率。
通过以上方式,你的控制器既保持了灵活性(支持任意组合筛选),又符合 Yii2 的设计规范,无需手动设置 header 或调用 json_encode() —— 框架会自动完成序列化、MIME 设置与字符编码处理。










