You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在WordPress中实现类似Laravel的请求类注入与验证

实现Laravel风格的自定义Request类(WordPress版)

1. 定义自定义请求基类

先封装一个通用的基类,兼容WordPress原生请求、处理验证逻辑,同时支持多场景复用:

abstract class BaseCustomRequest {
    protected WP_REST_Request $wpRequest;
    protected array $rules = [];
    protected array $messages = [];
    protected array $errors = [];

    // 从WP_REST_Request实例初始化(适配REST API场景)
    public static function fromWpRequest(WP_REST_Request $request): self {
        $instance = new static();
        $instance->wpRequest = $request;
        return $instance;
    }

    // 自动捕获当前请求(适配非REST场景,比如普通表单提交)
    public static function capture(): self {
        $instance = new static();
        if (defined('REST_REQUEST') && REST_REQUEST) {
            $instance->wpRequest = rest_get_current_request();
        } else {
            $instance->wpRequest = new WP_REST_Request();
            $instance->wpRequest->set_body_params($_POST);
            $instance->wpRequest->set_query_params($_GET);
        }
        return $instance;
    }

    // 验证规则,子类必须重写
    abstract protected function rules(): array;

    // 自定义错误提示,子类可选重写
    protected function messages(): array {
        return [];
    }

    // 执行验证逻辑
    public function validate(): bool {
        $this->rules = $this->rules();
        $this->messages = $this->messages();
        $validator = new WP_Error();

        foreach ($this->rules as $field => $rule) {
            $value = $this->wpRequest->get_param($field);
            // 实现基础验证规则,可按需扩展
            if (str_contains($rule, 'required') && empty($value)) {
                $validator->add($field, $this->messages["{$field}.required"] ?? ucfirst($field) . '不能为空');
            }
            if (str_contains($rule, 'email') && !is_email($value)) {
                $validator->add($field, $this->messages["{$field}.email"] ?? ucfirst($field) . '格式无效');
            }
            if (str_contains($rule, 'min:') && strlen($value) < (int)str_replace('min:', '', $rule)) {
                $min = str_replace('min:', '', $rule);
                $validator->add($field, $this->messages["{$field}.min"] ?? ucfirst($field) . "不能少于{$min}个字符");
            }
        }

        if ($validator->has_errors()) {
            $this->errors = $validator->get_error_messages();
            return false;
        }
        return true;
    }

    // 获取验证错误
    public function errors(): array {
        return $this->errors;
    }

    // 兼容Laravel风格的参数获取方法
    public function input(string $key, $default = null) {
        return $this->wpRequest->get_param($key) ?? $default;
    }

    // 获取所有请求参数
    public function all(): array {
        return $this->wpRequest->get_params();
    }
}

2. 定义具体的业务请求类

以注册请求为例,实现专属的验证规则:

class RegisterRequest extends BaseCustomRequest {
    protected function rules(): array {
        return [
            'username' => 'required|min:3',
            'email' => 'required|email',
            'password' => 'required|min:6'
        ];
    }

    protected function messages(): array {
        return [
            'username.required' => '用户名不能为空',
            'username.min' => '用户名至少3个字符',
            'email.required' => '邮箱不能为空',
            'email.email' => '请输入有效的邮箱地址',
            'password.required' => '密码不能为空',
            'password.min' => '密码至少6个字符'
        ];
    }
}

3. 解决REST API回调的类型匹配问题

方案一:通用注入包装器(推荐)

封装一个自动注入工具,识别回调参数中的自定义请求类,自动完成转换和验证:

class RequestInjector {
    public static function wrap(callable $callback): callable {
        return function(WP_REST_Request $wpRequest) use ($callback) {
            // 通过反射获取回调的参数类型
            $reflection = new ReflectionFunction($callback);
            $parameters = $reflection->getParameters();
            
            $args = [];
            foreach ($parameters as $param) {
                $type = $param->getType();
                // 判断是否为自定义请求类的子类
                if ($type instanceof ReflectionNamedType && is_subclass_of($type->getName(), BaseCustomRequest::class)) {
                    $customRequest = $type->getName()::fromWpRequest($wpRequest);
                    // 验证失败直接返回错误响应
                    if (!$customRequest->validate()) {
                        return new WP_REST_Response([
                            'success' => false,
                            'errors' => $customRequest->errors()
                        ], 422);
                    }
                    $args[] = $customRequest;
                } else {
                    // 其他类型参数直接传递
                    $args[] = $wpRequest;
                }
            }

            // 执行回调并返回结果
            return call_user_func_array($callback, $args);
        };
    }
}

注册路由时用包装器包裹回调:

register_rest_route($this->namespace, $this->baseRoute . '/register', [
    'methods'  => [WP_REST_Server::CREATABLE],
    'callback' => RequestInjector::wrap([$this, 'registerRouteCallback']),
]);

此时回调方法可直接接收自定义请求类:

public function registerRouteCallback(RegisterRequest $request)
{
    // 直接使用自定义请求类的方法
    $username = $request->input('username');
    $email = $request->input('email');
    
    // 业务逻辑处理...
    
    return new WP_REST_Response([
        'success' => true,
        'message' => '注册成功'
    ], 200);
}

方案二:路由中间件(按需使用)

如果需要针对单个路由做特殊处理,可以用REST API中间件直接转换请求:

register_rest_route($this->namespace, $this->baseRoute . '/register', [
    'methods'  => [WP_REST_Server::CREATABLE],
    'callback' => [$this, 'registerRouteCallback'],
    'middleware' => [function(WP_REST_Request $request, $handler) {
        $customRequest = RegisterRequest::fromWpRequest($request);
        if (!$customRequest->validate()) {
            return new WP_REST_Response([
                'success' => false,
                'errors' => $customRequest->errors()
            ], 422);
        }
        // 把自定义请求传递给回调
        return $handler($customRequest);
    }]
]);

4. 多场景复用(非REST API场景)

在普通页面、短代码或钩子中,直接用capture()方法自动捕获请求:

// 短代码示例:注册表单处理
function register_form_shortcode() {
    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        $request = RegisterRequest::capture();
        if ($request->validate()) {
            // 执行注册逻辑
            return '<p style="color:green;">注册成功!</p>';
        } else {
            $errors = implode('<br>', $request->errors());
            return "<p style='color:red;'>{$errors}</p>";
        }
    }
    // 渲染注册表单
    return '
        <form method="post">
            <input type="text" name="username" placeholder="用户名">
            <input type="email" name="email" placeholder="邮箱">
            <input type="password" name="password" placeholder="密码">
            <button type="submit">注册</button>
        </form>
    ';
}
add_shortcode('register_form', 'register_form_shortcode');

内容的提问来源于stack exchange,提问作者Chandler P.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 18:11:03