PHP验证场景怎么区分

wen PHP项目 1

本文目录导读:

PHP验证场景怎么区分

  1. 方法一:根据请求方法区分(最常用)
  2. 方法二:显式传递场景参数(最灵活)
  3. 方法三:根据 ID 参数区分(简单直接)
  4. 方法四:使用验证器类封装(推荐用于复杂项目)
  5. 总结与建议

在 PHP 中区分不同的验证场景(如“新增”和“编辑”),核心思路是根据当前操作的状态或来源数据,动态调整验证规则

由于 PHP 不像 Laravel 那样有内置的 FormRequest 场景概念,你需要自己实现逻辑,以下是几种最常用、最清晰的区分方法:

根据请求方法区分(最常用)

这是最直观的方法,尤其适用于 RESTful 风格接口。

  • 新增:通常对应 POSTPUT 方法。
  • 编辑:通常对应 PATCHPOST(带 ID 参数)。

代码示例:

<?php
function validateUserInput($request) {
    $rules = [];
    if ($request->isMethod('POST')) {
        // 新增场景:邮箱必须唯一,密码必填
        $rules['email'] = 'required|email|unique:users,email';
        $rules['password'] = 'required|min:6';
    } elseif ($request->isMethod('PATCH') || $request->isMethod('PUT')) {
        // 编辑场景:邮箱唯一性验证排除当前用户,密码可选
        $rules['email'] = 'required|email|unique:users,email,' . $request->id;
        $rules['password'] = 'sometimes|min:6'; // 仅在填写时验证
    }
    // 公共规则
    $rules['name'] = 'required|max:255';
    return performValidation($request->all(), $rules);
}

优点:简单、符合 HTTP 语义。 缺点:如果接口设计不标准(如全部用 POST),则无法区分。


显式传递场景参数(最灵活)

在请求中增加一个隐藏字段或 GET 参数(如 _scenario),前端告诉后端“我是谁”。

代码示例:

<?php
function validateProduct($data, $scenario = 'create') {
    $rules = [
        'title' => 'required|max:200',
    ];
    if ($scenario === 'create') {
        // 新增:必须上传图片,SKU唯一
        $rules['image'] = 'required|image';
        $rules['sku'] = 'required|unique:products';
    } elseif ($scenario === 'update') {
        // 编辑:图片可选,SKU唯一性排除自身
        $rules['image'] = 'sometimes|image';
        $rules['sku'] = 'required|unique:products,sku,' . ($data['id'] ?? 0);
    }
    return performValidation($data, $rules);
}
// 前端调用
// validateProduct($_POST, $_POST['_scenario'] ?? 'create');

优点:完全由开发者控制,适应任何不标准的接口。 缺点:需要前后端约定好字段名,前端可能篡改。


根据 ID 参数区分(简单直接)

判断请求数据中是否存在“主键 ID”,如果存在则视为编辑,否则视为新增。

代码示例:

<?php
function validateArticle($data) {
    $isUpdate = !empty($data['id']);
    $rules = [
        'content' => 'required|max:10000',
    ];
    if ($isUpdate) {
        // 编辑模式
        $rules['title'] = 'required|max:100';
        // 对唯一性验证排除当前记录
        $rules['slug'] = 'required|unique:articles,slug,' . $data['id'];
    } else {
        // 新增模式
        $rules['title'] = 'required|max:100|unique:articles'; // 标题全局唯一
        $rules['slug'] = 'required|unique:articles'; // slug全局唯一
    }
    return performValidation($data, $rules);
}

优点:无需额外参数,代码自解释。 缺点:如果表单 ID 字段永远为空或不存在,则需谨慎处理。


使用验证器类封装(推荐用于复杂项目)

如果项目较大,建议将验证逻辑封装成类,通过方法名定义场景。

代码示例(实现一个简单的场景验证器):

<?php
class UserValidator {
    protected $data;
    protected $rules = [];
    public function __construct($data) {
        $this->data = $data;
    }
    // 设置场景:'create' 或 'update'
    public function setScenario($scenario) {
        switch ($scenario) {
            case 'create':
                $this->rules = [
                    'email' => 'required|email|unique:users',
                    'password' => 'required|min:8',
                    'name' => 'required',
                ];
                break;
            case 'update':
                $this->rules = [
                    'email' => 'required|email|unique:users,email,' . ($this->data['id'] ?? 0),
                    'password' => 'sometimes|min:8',
                    'name' => 'required',
                ];
                break;
            default:
                throw new \InvalidArgumentException("Invalid scenario: $scenario");
        }
        return $this;
    }
    public function validate() {
        // 执行验证逻辑(如调用 PHP 原生 filter_var 或第三方库)
        // ...
        if (!filter_var($this->data['email'], FILTER_VALIDATE_EMAIL)) {
            throw new \Exception('Email 格式错误');
        }
        // 实际项目中建议使用 symfony/validator 或 valitron
        return true;
    }
}
// 使用方式
$validator = new UserValidator($_POST);
$validator->setScenario('create')->validate(); // 新增时验证

优点:结构清晰,易于扩展,可测试性好。 缺点:需要额外编写类代码。


总结与建议

方案 适用场景 推荐指数
请求方法区分 RESTful API,前后端分离 ⭐⭐⭐⭐⭐
显式场景参数 旧系统改造,表单非标准 ⭐⭐⭐⭐
根据 ID 区分 简单的 CRUD 操作 ⭐⭐⭐⭐
验证器类封装 大型项目,逻辑复用要求高 ⭐⭐⭐⭐⭐(强烈推荐)

最佳实践建议:

  1. 优先选择方案 1 + 方案 3 结合:先判断 HTTP 方法,再辅以 ID 存在性判断。
  2. 使用验证库:不要自己写验证逻辑,推荐使用 symfony/validator(全功能)或 vlucas/valitron(轻量)。
  3. 唯一性验证的特殊处理
    • 编辑场景下验证唯一字段(如 Email、手机号)时,必须排除当前记录自身,否则会报“该邮箱已存在”的错误。
    • SQL 示例:SELECT 1 FROM users WHERE email = ? AND id != ?
  4. 前后端约定:确保前端能正确传递表示“场景”的参数,或保持接口风格统一。

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