yii2中批量参数校验推荐用自定义验证器(如timerangevalidator)配合scenarios和rules统一管理,挂载于某一字段但校验多字段关联逻辑,控制器只需调用validate()即可触发全部规则并统一返回错误。

Yii2 中实现批量参数校验,推荐使用自定义验证器配合 scenarios 和 rules 统一管理,避免在控制器里写一堆 if 判断。核心是把多个字段的关联逻辑封装进一个验证器,让模型自动触发校验。
定义一个批量校验用的自定义验证器
比如要校验「开始时间」和「结束时间」是否构成合法的时间区间,且不能跨天超过 7 天:
namespace app\validators;
use yii\validators\Validator;
use DateTime;
class TimeRangeValidator extends Validator
{
public $minDays = 1;
public $maxDays = 7;
public function validateAttribute($model, $attribute)
{
$start = $model->start_time;
$end = $model->end_time;
if (empty($start) || empty($end)) {
$this->addError($model, $attribute, '开始时间和结束时间都必须填写');
return;
}
try {
$s = new DateTime($start);
$e = new DateTime($end);
} catch (\Exception $ex) {
$this->addError($model, $attribute, '时间格式不正确');
return;
}
if ($s > $e) {
$this->addError($model, $attribute, '结束时间不能早于开始时间');
return;
}
$diff = $e->diff($s)->days;
if ($diff minDays || $diff > $this->maxDays) {
$this->addError($model, $attribute, "时间跨度必须在 {$this->minDays}–{$this->maxDays} 天内");
}
}
}
在模型中注册并使用该验证器
注意:这个验证器挂载在某个字段上(如 end_time),但实际校验的是两个字段的组合关系:
namespace app\models;
use yii\db\ActiveRecord;
use app\validators\TimeRangeValidator;
class EventForm extends ActiveRecord
{
public $start_time;
public $end_time;
public function rules()
{
return [
[['start_time', 'end_time'], 'required'],
[['start_time', 'end_time'], 'string', 'max' => 19],
['end_time', TimeRangeValidator::class], // 关键:挂载到 end_time,内部自动检查 start_time
];
}
public function scenarios()
{
return [
'create' => ['start_time', 'end_time'],
'update' => ['start_time', 'end_time'],
];
}
}
控制器中统一调用校验
无需手动判断每个字段,直接调用 validate() 即可触发全部规则,包括自定义验证器:
public function actionCreate()
{
$form = new EventForm(['scenario' => 'create']);
if ($form->load(\Yii::$app->request->post()) && $form->validate()) {
// 校验通过,执行业务逻辑
return $this->asJson(['success' => true]);
}
// 返回所有错误(含自定义验证器产生的)
return $this->asJson([
'success' => false,
'errors' => $form->getErrors()
]);
}
进阶技巧:支持多字段动态传参
如果想让验证器更通用(比如适配不同字段名),可在验证器中加属性控制:
- 添加
public $startTimeAttribute = 'start_time';和$endTimeAttribute - 在
validateAttribute中用$model->{$this->startTimeAttribute}取值 - 规则中这样写:
['end_time', TimeRangeValidator::class, 'startTimeAttribute' => 'start_time']
这样一套机制就能复用于多个模型或不同字段组合,保持代码简洁、校验集中、错误统一返回。











