beforeaction 不负责表单验证,也不能设置 json 验证;它仅是请求前置钩子,验证必须由模型 rules() 定义并在 action 中调用 load() 和 validate() 才触发。

在 Yii2 控制器中,beforeAction 本身**不负责表单验证**,也不能直接“设置 JSON 验证”。它只是请求处理流程中的前置钩子,常被误用于响应格式配置(如设为 JSON),但和表单数据校验逻辑无关。表单验证由模型(Model)驱动,必须通过 rules() 定义,并在控制器中显式调用 $model->load() 和 $model->validate() 才会触发。
beforeAction 的常见误用与正确定位
很多人在 beforeAction 里写:
-
Yii::$app->response->format = Response::FORMAT_JSON;—— 这是设置响应格式,让返回变成 JSON,和“验证”无关; - 试图在里面调用
$model->validate()—— 模型实例尚未创建或未加载数据,此时验证无意义,也容易出错; - 把验证规则写进
beforeAction—— 规则只能定义在模型的rules()方法中,框架只认这个入口。
JSON 接口下表单验证的正确流程
当你开发的是 API 接口(返回 JSON),验证仍需走标准模型流程,只是响应方式不同:
使用 JSON Schema 验证 JSON 数据,从示例 JSON 生成 schema,并将其转换为 TypeScript 接口、Python 数据类或 Markdown 文档。
- 在 action 开头设置响应格式:
Yii::$app->response->format = Response::FORMAT_JSON; - 用
$model->load(Yii::$app->request->bodyParams, '')加载 JSON 请求体(注意第二个参数为空字符串,避免默认前缀); - 调用
$model->validate(); - 验证失败时,手动 return 错误数组,例如:
return ['success' => false, 'errors' => $model->errors]; - 验证成功后继续业务逻辑,最后 return 正常数据。
避免踩坑的关键细节
JSON 请求体解析和验证有几个易错点:
- 前端发送的是
application/json,但 Yii 默认不自动解析 body —— 必须启用Yii::$app->request->enableCsrfValidation = false;(API 通常关 CSRF),并确认bodyParams已被正确解析(可通过var_dump(Yii::$app->request->bodyParams)调试); -
required验证器对0、false、空字符串会判为“缺失”,若字段允许数字 0,应配合'requiredValue' => null或改用filter + default预处理; - 自定义验证方法必须是
public,签名严格为function($attribute, $params),失败时调用$this->addError($attribute, $message),不能 return false。
一个精简可用的 API action 示例
不需要在 beforeAction 做验证,下面这段放在具体 action 里即可:
public function actionCreate()
{
Yii::$app->response->format = Response::FORMAT_JSON;
$model = new UserForm();
$model->load(Yii::$app->request->bodyParams, '');
if (!$model->validate()) {
return ['success' => false, 'errors' => $model->errors];
}
if ($model->save()) {
return ['success' => true, 'data' => $model->attributes];
}
return ['success' => false, 'message' => '保存失败'];
}










