Laravel 9多场景API验证实现求助(需自定义规则示例)
解决方案:Laravel 9 多场景API验证实现
一、核心实现方案
针对你的需求,我们采用FormRequest类(Laravel复杂验证推荐方案)结合自定义验证规则,实现动态场景控制、字段格式校验及依赖验证逻辑。
二、场景1:依source动态控制company_number与gst_number
实现步骤
- 创建
CompanyRequest.php(存放于app/Http/Requests目录) - 在
rules()方法中根据source值动态生成对应验证规则 - 利用
required_without、prohibited等规则匹配场景逻辑
代码示例
<?php namespace App\Http\Requests; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Validation\Rule; class CompanyRequest extends FormRequest { // 开启验证失败即终止,提升效率 protected $stopOnFirstFailure = true; public function authorize() { return true; // 可根据实际权限逻辑调整 } public function rules() { $baseRules = [ 'company_name' => ['required', 'string'], 'country' => ['required', 'string', 'regex:/^[A-Z]{2}$/', Rule::exists('countries', 'iso_code')], 'source' => ['required', 'numeric', Rule::exists('sources', 'id')], ]; // 根据source值匹配对应验证规则 switch ($this->source) { case 1: // source=1时,两个字段均非必填 $baseRules['company_number'] = ['nullable', 'string']; $baseRules['gst_number'] = ['nullable', 'string', 'regex:/^([0-9]{2}[a-zA-Z]{5}[0-9]{4}[a-zA-Z]{1}[0-9]{1}Z{1}[0-9A-Za-z]{1})$/']; break; case 2: // source=2时,必填其一且不可同时存在 $baseRules['company_number'] = ['required_without:gst_number', 'string', 'prohibited_if:gst_number,!null']; $baseRules['gst_number'] = ['required_without:company_number', 'string', 'prohibited_if:company_number,!null', 'regex:/^([0-9]{2}[a-zA-Z]{5}[0-9]{4}[a-zA-Z]{1}[0-9]{1}Z{1}[0-9A-Za-z]{1})$/']; break; default: // source为其他值时,仅允许company_number,禁止gst_number $baseRules['company_number'] = ['required', 'string']; $baseRules['gst_number'] = ['prohibited']; break; } // 合并country-state验证规则 $baseRules = array_merge($baseRules, $this->getCountryStateRules()); return $baseRules; } // 自定义错误提示(可选) public function messages() { return [ 'gst_number.prohibited' => '当前source值不允许提交gst_number', 'state.prohibited' => '当前国家无需填写state字段', 'state.belongs_to_country' => 'state不属于当前国家的有效列表', ]; } }
三、场景2:Country-State映射验证
实现步骤
- 创建自定义验证规则
BelongsToCountry.php(存放于app/Rules目录) - 在FormRequest中调用该规则,结合
prohibited、required_if完成场景校验
1. 自定义验证规则BelongsToCountry.php
<?php namespace App\Rules; use Illuminate\Contracts\Validation\Rule; class BelongsToCountry implements Rule { protected $country; public function __construct($country) { $this->country = $country; } public function passes($attribute, $value) { // 替换为你已有的国家-state映射列表 $countryStates = [ 'X' => ['CA', 'NY'], 'Y' => ['TX', 'FL'], 'Z' => ['ON', 'QC'], ]; return isset($countryStates[$this->country]) && in_array($value, $countryStates[$this->country]); } public function message() { return 'state不属于当前国家的有效列表'; } }
2. 在FormRequest中添加Country-State规则
在CompanyRequest.php中新增方法:
protected function getCountryStateRules() { $rules = []; // 强制校验state格式:无论是否必填,空值或格式错误直接报错 $rules['state'] = [ 'string', 'regex:/^[A-Z]{2}$/', // 非X/Y/Z国家禁止提交state Rule::prohibitedIf(!in_array($this->country, ['X', 'Y', 'Z'])), // X/Y/Z国家必须提交state Rule::requiredIf(in_array($this->country, ['X', 'Y', 'Z'])), // 校验state是否属于对应国家 new \App\Rules\BelongsToCountry($this->country), ]; return $rules; }
四、多余字段处理
若需对多余字段触发验证错误,可在CompanyRequest.php中添加以下逻辑:
protected function prepareForValidation() { $allowedFields = ['company_name', 'company_number', 'gst_number', 'country', 'state', 'source']; $extraFields = array_diff(array_keys($this->all()), $allowedFields); if (!empty($extraFields)) { throw new \Illuminate\Validation\ValidationException( \Illuminate\Validation\Validator::make([], [])->errors()->add('extra_fields', '不允许提交以下字段: ' . implode(',', $extraFields)) ); } }
五、控制器中使用
在API控制器中直接注入CompanyRequest即可自动触发验证:
public function store(CompanyRequest $request) { // 验证通过后获取合规数据 $validatedData = $request->validated(); // 后续业务逻辑处理 }
内容的提问来源于stack exchange,提问作者Varun Krishnan
相关产品推荐
相关产品推荐

