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

更新用户时忽略当前用户字段唯一校验及auth获取为空问题

更新当前用户数据时跳过自身字段唯一性校验的实现方法

问题根因

自定义验证器中auth()->id()返回null,是因为你将@guard(with: ["api"])声明在了单个mutation字段上:Lighthouse字段级守卫的执行时机晚于输入验证阶段,验证器运行时认证逻辑还未启动,全局auth上下文未初始化,自然无法获取到登录用户ID。
同时你同时在SDL的Input定义中写了@rules、又编写了自定义验证器类,两套校验规则重复,会产生规则冲突。

具体实现步骤

  1. 清理重复规则:删除UpdateUserInput类型中所有字段上的@rules注解,所有校验规则统一在自定义验证器类中维护,避免双重校验。
  2. 调整更新字段的非空标记:更新场景下通常支持部分字段修改,去掉SDL中字段后的!非空强制标记,配合验证器的sometimes规则使用,否则不传对应字段会直接被GraphQL层拦截,无法走到自定义验证逻辑:
    input UpdateUserInput {
        name: String
        lastname: String
        username: String
        email: String
        phone: String
    }
    
  3. 解决验证器中获取用户ID为空的问题,二选一即可
    • 方案一(推荐):调整守卫执行时机
      在config/lighthouse.php配置文件中,将默认守卫设置为api,让认证逻辑在请求进入验证流程前就完成初始化:
      'guard' => 'api',
      
      配置完成后,验证器rules()方法内的auth()->id()就能正常返回当前登录用户ID,你原来写的Rule::unique()->ignore($id)逻辑即可正常生效,自动跳过当前用户自身的唯一校验。
    • 方案二:直接从请求上下文取用户
      如果不想修改全局守卫配置,可以不依赖auth()助手,直接从Lighthouse注入的请求属性中获取当前用户:
      public function rules(): array
      {
          // 直接从Lighthouse上下文取用户,无需等待全局auth初始化
          $userId = request()->attributes->get('lighthouse-user')?->id;
      
          return [
              'name' => ['sometimes', 'string', 'between:2,25'],
              'lastname' => ['sometimes', 'string', 'between:2,25'],
              'username' => [
                  'sometimes',
                  'string',
                  'between:2,12',
                  // 补全正则结束锚点,避免非法字符绕过校验
                  'regex:/^[a-zA-Z0-9]+$/',
                  Rule::unique('users', 'username')->ignore($userId),
              ],
              'email' => [
                  'sometimes',
                  'string',
                  'email',
                  'max:255',
                  Rule::unique('users', 'email')->ignore($userId),
              ],
              'phone' => [
                  'sometimes',
                  // 补全正则起止锚点,避免非10位数字绕过校验
                  'regex:/^[0-9]{10}$/',
                  Rule::unique('users', 'phone')->ignore($userId),
              ],
          ];
      }
      

校验规则优化提示

你原来写的正则规则缺少结束锚点,存在校验绕过风险:

  • 原username正则/^[a-zA-Z0-9]+/只校验开头是字母数字,后续加特殊字符也能通过校验
  • 原phone正则/[0-9]{10}/只校验字符串中存在连续10位数字,前后加其他字符、数字长度超过10位都能通过校验
    建议按上述代码补全^和$锚点,保证校验准确性。

内容的提问来源于stack exchange,提问作者devmrh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 17:36:20