PHP 请求验证层放哪

wen PHP项目 1

本文目录导读:

PHP 请求验证层放哪

  1. 控制器内验证(小型项目)
  2. FormRequest 类(Laravel 推荐)
  3. Service 层验证(大型项目/DDD)
  4. 中间件验证(特定场景)
  5. 独立验证层(复杂业务)
  6. 推荐方案对比
  7. 最佳实践建议

在 PHP 项目中,请求验证层的放置位置取决于你的项目架构,以下是常见的几种方案:

控制器内验证(小型项目)

class UserController extends Controller
{
    public function store(Request $request)
    {
        $validated = $request->validate([
            'name' => 'required|string|max:255',
            'email' => 'required|email|unique:users',
            'password' => 'required|min:8'
        ]);
        // 处理业务逻辑
    }
}

FormRequest 类(Laravel 推荐)

// app/Http/Requests/StoreUserRequest.php
class StoreUserRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }
    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)
    {
        $validated = $request->validated();
        // 业务逻辑
    }
}

Service 层验证(大型项目/DDD)

// app/Services/UserService.php
class UserService
{
    private UserValidator $validator;
    public function __construct(UserValidator $validator)
    {
        $this->validator = $validator;
    }
    public function create(array $data)
    {
        $validatedData = $this->validator->validate($data);
        // 业务逻辑
    }
}
// app/Validators/UserValidator.php
class UserValidator
{
    public function validate(array $data): array
    {
        $validator = Validator::make($data, [
            'name' => 'required|string|max:255',
            'email' => 'required|email|unique:users'
        ]);
        if ($validator->fails()) {
            throw new ValidationException($validator);
        }
        return $validator->validated();
    }
}

中间件验证(特定场景)

// app/Http/Middleware/ValidateApiKey.php
class ValidateApiKey
{
    public function handle($request, Closure $next)
    {
        if (!$request->has('api_key')) {
            return response()->json(['error' => 'Missing API key'], 400);
        }
        return $next($request);
    }
}
// 路由中使用
Route::middleware(['validate.api.key'])->group(function () {
    Route::post('/data', [DataController::class, 'store']);
});

独立验证层(复杂业务)

app/
├── Http/
│   ├── Controllers/
│   └── Requests/           # FormRequest 放这里
├── Services/
│   └── UserService.php     # 业务逻辑
├── Validators/
│   ├── UserValidator.php
│   └── OrderValidator.php
├── Models/
└── Rules/                  # 自定义验证规则
    ├── UniqueTogether.php
    └── PhoneNumber.php

推荐方案对比

小型项目 (Laravel)

  • 使用 FormRequest(方案2)
  • 简单直观,自动处理错误响应

中型项目

  • FormRequest + Service 层
  • 验证逻辑集中在 Request 类,业务逻辑在 Service

大型项目/微服务

  • 独立 Validator 类(方案3)
  • 解耦清晰,便于单元测试
  • 支持复杂验证逻辑复用

API 服务

  • 结合中间件(方案4)处理认证/API Key
  • 使用 FormRequest 处理数据验证
  • 统一错误响应格式

最佳实践建议

  1. 保持验证集中:避免验证逻辑分散在各处
  2. 错误信息统一:使用统一的错误响应格式
  3. 验证优先级:先格式验证,再业务验证,最后权限验证
// 组合使用示例
class UserController extends Controller
{
    public function store(StoreUserRequest $request)
    {
        // 1. 先通过 FormRequest 进行格式验证
        $validated = $request->validated();
        // 2. 再在 Service 层进行业务验证
        $this->userService->create($validated);
        return response()->json(['message' => '用户创建成功'], 201);
    }
}

选择哪种方案主要看项目规模和团队协作需求,重点是保持验证逻辑的可维护性和一致性。

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