如何在Lighthouse GraphQL的Mutation中实现排除自身的唯一验证
解决方案:在Input内实现排除自身的唯一验证
方法1:利用Laravel内置unique规则+动态参数
修改你的VoteCategoryInput定义,给name字段的@rules指令添加排除当前ID的条件,通过Lighthouse的参数占位符获取更新的ID:
input VoteCategoryInput { name: String! @rules(apply: [ "required", "unique:vote_categories,name,{{$args.id}}" ]) # 其他字段(如描述、状态等) }
对应的updateVoteCategory Mutation定义需要明确接收id参数:
type Mutation { updateVoteCategory(id: ID!, input: VoteCategoryInput!): VoteCategory @update }
这里{{$args.id}}会自动引用Mutation的id参数,Laravel的unique规则会自动排除该ID对应的记录,避免更新时检测到自身重复。
方法2:自定义验证规则类(更灵活)
如果需要更复杂的逻辑,比如多字段联合唯一,或者需要额外判断,可以自定义Laravel验证规则类:
- 创建规则类
app/Rules/UniqueVoteCategoryName.php:
<?php namespace App\Rules; use Illuminate\Contracts\Validation\Rule; use Illuminate\Support\Facades\Request; class UniqueVoteCategoryName implements Rule { protected $ignoreId; public function __construct() { // 从GraphQL请求参数中获取要更新的ID $graphqlArgs = Request::get('variables'); $this->ignoreId = $graphqlArgs['id'] ?? null; } public function passes($attribute, $value) { $query = \App\Models\VoteCategory::where('name', $value); // 如果是更新操作,排除当前ID的记录 if ($this->ignoreId) { $query->where('id', '!=', $this->ignoreId); } return !$query->exists(); } public function message() { return '投票分类名称已存在,请更换其他名称'; } }
- 在
VoteCategoryInput中引用该规则:
input VoteCategoryInput { name: String! @rule(apply: ["required", "App\\Rules\\UniqueVoteCategoryName"]) # 其他字段 }
解决自定义验证器的类型转换/必填问题
如果之前用@validator指令关联到Mutation时出现必填错误,可能是因为验证器没有正确处理Input的结构。正确的验证器写法应该直接从验证数据中获取Input字段:
<?php namespace App\Validators; use Nuwave\Lighthouse\Validation\Validator; class VoteCategoryInputValidator extends Validator { public function rules(): array { $id = $this->args['id']; return [ 'input.name' => [ 'required', \Illuminate\Validation\Rule::unique('vote_categories')->ignore($id) ] ]; } public function messages(): array { return [ 'input.name.unique' => '投票分类名称已存在' ]; } }
然后在Mutation中关联:
type Mutation { updateVoteCategory(id: ID!, input: VoteCategoryInput!): VoteCategory @update @validator(class: "App\\Validators\\VoteCategoryInputValidator") }
这种方式下,验证器直接复用Laravel的Rule::unique()->ignore()逻辑,自动处理排除自身的需求,同时避免类型转换问题。
内容的提问来源于stack exchange,提问作者mstdmstd
相关产品推荐
相关产品推荐

