本文目录导读:

是的,Laravel 表单请求验证(Form Request Validation)完全可以复用,而且它是 Laravel 推荐的最佳实践之一,以下是几种常见的复用方式:
直接复用同一个 Form Request 类
最直接的方式是在多个控制器方法中注入同一个 Form Request 类:
// app/Http/Requests/StoreUserRequest.php
class StoreUserRequest extends FormRequest
{
public function rules()
{
return [
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users',
'password' => 'required|min:8',
];
}
}
// 在多个控制器方法中使用
class UserController extends Controller
{
public function store(StoreUserRequest $request) { }
public function update(StoreUserRequest $request, $id) { }
public function apiStore(StoreUserRequest $request) { }
}
通过继承复用
创建基类 Request,子类继承并扩展:
// app/Http/Requests/BaseUserRequest.php
class BaseUserRequest extends FormRequest
{
public function rules()
{
return [
'name' => 'required|string|max:255',
'email' => 'required|email',
];
}
}
// app/Http/Requests/StoreUserRequest.php
class StoreUserRequest extends BaseUserRequest
{
public function rules()
{
return array_merge(parent::rules(), [
'password' => 'required|min:8',
]);
}
}
// app/Http/Requests/UpdateUserRequest.php
class UpdateUserRequest extends BaseUserRequest
{
public function rules()
{
return array_merge(parent::rules(), [
'password' => 'sometimes|min:8',
]);
}
}
使用 Trait 复用验证规则
// app/Http/Requests/Traits/UserValidationRules.php
trait UserValidationRules
{
protected function baseUserRules(): array
{
return [
'name' => 'required|string|max:255',
'email' => 'required|email',
'phone' => 'nullable|string|max:20',
];
}
protected function passwordRules(bool $required = true): array
{
$rules = ['min:8', 'confirmed'];
if ($required) {
array_unshift($rules, 'required');
} else {
array_unshift($rules, 'sometimes');
}
return ['password' => $rules];
}
}
// 在多个 Form Request 中使用
class StoreUserRequest extends FormRequest
{
use UserValidationRules;
public function rules()
{
return array_merge(
$this->baseUserRules(),
$this->passwordRules(true)
);
}
}
class UpdateUserRequest extends FormRequest
{
use UserValidationRules;
public function rules()
{
return array_merge(
$this->baseUserRules(),
$this->passwordRules(false)
);
}
}
动态规则生成(高级复用)
// app/Http/Requests/DynamicUserRequest.php
class DynamicUserRequest extends FormRequest
{
public function rules()
{
$rules = [
'name' => 'required|string|max:255',
'email' => 'required|email',
];
// 根据不同场景动态添加规则
if ($this->isMethod('POST')) {
$rules['email'] .= '|unique:users';
$rules['password'] = 'required|min:8';
} elseif ($this->isMethod('PUT') || $this->isMethod('PATCH')) {
$rules['email'] .= '|unique:users,email,' . $this->route('user');
$rules['password'] = 'sometimes|min:8';
}
return $rules;
}
}
// 使用
Route::post('/users', [UserController::class, 'store']);
Route::put('/users/{user}', [UserController::class, 'update']);
// 两个路由都使用 DynamicUserRequest
自定义验证规则复用
// app/Rules/PhoneNumber.php
class PhoneNumber implements Rule
{
public function passes($attribute, $value)
{
return preg_match('/^1[3-9]\d{9}$/', $value);
}
public function message()
{
return '手机号格式不正确';
}
}
// 在任何 Form Request 中使用
class UserRequest extends FormRequest
{
public function rules()
{
return [
'phone' => ['required', new PhoneNumber],
];
}
}
通过服务容器绑定复用
// AppServiceProvider.php
public function boot()
{
$this->app->bind(StoreUserRequest::class, function ($app) {
return new StoreUserRequest();
});
}
// 控制器注入
public function store(StoreUserRequest $request) { }
public function apiStore(StoreUserRequest $request) { }
最佳实践建议
- 按业务场景分组:根据业务模块创建对应的 Request 类
- 使用继承:创建基础 Request 类,子类只添加差异部分
- 提取公共规则:将重复的验证规则提取到 Trait 或自定义规则类
- 保持单一职责:每个 Request 类只负责一个场景的验证
通过合理复用 Form Request,可以显著减少代码重复,提高维护性和一致性。