Laravel表单请求验证能复用吗

wen PHP项目 1

本文目录导读:

Laravel表单请求验证能复用吗

  1. 直接复用同一个 Form Request 类
  2. 通过继承复用
  3. 使用 Trait 复用验证规则
  4. 动态规则生成(高级复用)
  5. 自定义验证规则复用
  6. 通过服务容器绑定复用
  7. 最佳实践建议

是的,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) { }

最佳实践建议

  1. 按业务场景分组:根据业务模块创建对应的 Request 类
  2. 使用继承:创建基础 Request 类,子类只添加差异部分
  3. 提取公共规则:将重复的验证规则提取到 Trait 或自定义规则类
  4. 保持单一职责:每个 Request 类只负责一个场景的验证

通过合理复用 Form Request,可以显著减少代码重复,提高维护性和一致性。

抱歉,评论功能暂时关闭!