I have input with unique rule:
input VoteCategoryInput {
name: String! @rules(apply: ["string", "min:2", "max:255", "unique:vote_categories,name"]),
active: Boolean!,
in_subscriptions: Boolean!,
meta_description: String,
meta_keywords: [String],
}
extend type Mutation {
createVoteCategory(
input: VoteCategoryInput! @spread
): VoteCategory! @create
updateVoteCategory(
id: ID!,
input: VoteCategoryInput! @spread
): VoteCategory! @update
deleteVoteCategory(id: ID! @whereKey): VoteCategory @delete
}
and running mutation for existing rows = 10:
mutation {
updateVoteCategory(
id: 10
input: {
name: "UPDATED Vote Category 11"
active: false
in_subscriptions: false
meta_keywords: ["meta_keywords UPDATED 1", "meta_keywords UPDATED2"]
}
) {
id
name
slug
in_subscriptions
meta_description
meta_keywords
created_at
updated_at
}
}
I got error with unique rule break : in checking sql tracement I do not see condition id <> 10 - so this checking statement find itself. I tried to put unique rule out of input :
input VoteCategoryInput {
active: Boolean!,
in_subscriptions: Boolean!,
meta_description: String,
meta_keywords: [String],
}
extend type Mutation {
createVoteCategory(
name: String! @rules(apply: ["string", "min:2", "max:255", "unique:vote_categories,name"]),
input: VoteCategoryInput! @spread
): VoteCategory! @create
updateVoteCategory(
id: ID!,
name: String! @rules(apply: ["string", "min:2", "max:255"]),
input: VoteCategoryInput! @spread
): VoteCategory! @update
deleteVoteCategory(id: ID! @whereKey): VoteCategory @delete
}
and with mutation :
mutation {
updateVoteCategory(
id: 10
name: "Vote Category name #8"
input: {
active: false
in_subscriptions: false
meta_keywords: ["meta_keywords UPDATED 1", "meta_keywords UPDATED2"]
}
) {
id
name
slug
in_subscriptions
meta_description
meta_keywords
created_at
updated_at
}
}
But Now I got
SQLSTATE[23000]: Integrity constraint violation
if name "Vote Category name #8" was found with other id - this mutation did not use any unique check.
How cat it be fixed ? I would prefer 1st way with name rule inside of input... I did not find any similar option in docs at https://lighthouse-php.com/6/api-reference/directives.html#rules
UPDATED # 1:
I cretated a new validator with command :
php artisan lighthouse:validator VoteCategoryInputValidator
and got php file app/GraphQL/Validators/VoteCategoryInputValidator.php in which I can fill rules and messages methods which I can fill as I do in laravel app.
Next I need to assign VoteCategoryInputValidator to my mutation and I tried to add line in grqph file in input block:
input VoteCategoryInput {
name: String! @rules(apply: ["string", "min:2", "max:255", "unique:vote_categories,name"]),
active: Boolean!,
in_subscriptions: Boolean!,
meta_description: String,
meta_keywords: [String],
@rules(apply: ["App\\GraphQL\\Validators\\VoteCategoryInputValidator"])
}
I found reference to it at docs https://lighthouse-php.com/6/security/validation.html#single-arguments in “Custom Validation Rules” blocks
But I got error :
Object of class App\\GraphQL\\Validators\\VoteCategoryInputValidator could not be converted to string",
Is it invalid syntax ?
UPDATED # 2:
With syntax :
updateVoteCategory(
id: ID!,
input: VoteCategoryInput! @spread
): VoteCategory!
@validator(class: "app\\GraphQL\\Validators\\UpdateVoteCategoryValidator")
@update
I return array of rules in UpdateVoteCategoryValidator, but now I get list of errors for all fields :
"errors": [
{
"message": "Validation failed for the field [updateVoteCategory].",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"updateVoteCategory"
],
"extensions": {
"validation": {
"name": [
"The name field is required."
],
"active": [
"The active field is required."
],
"in_subscriptions": [
"The in subscriptions field is required."
],
"input.name": [
"The input.name has already been taken."
]
},
I suppose that is as I use input, but how can I use input in UpdateVoteCategoryValidator ?
I suggest using the @validator
like the lighthouse docs. In there is an example with Rule::unique('users', 'name')->ignore($this->arg('id'), 'id');
on the UpdateUserInputValidator
. With the @rule
directive they don't have any example with unique and the ID as you want.
You access the validator key values with $this->arg('key')
.
schema
input VoteCategoryInput {
name: String!,
active: Boolean!,
in_subscriptions: Boolean!,
meta_description: String,
meta_keywords: [String],
}
extend type Mutation {
createVoteCategory(
input: VoteCategoryInput! @spread
): VoteCategory!
@validator(class: "App\\GraphQL\\Validators\\CreateVoteCategoryValidator")
@create
updateVoteCategory(
id: ID!,
input: VoteCategoryInput! @spread #if you use the @spread, you don't need to use the key 'input.field' on the validator class because will "flat" the input.
): VoteCategory!
@validator(class: "App\\GraphQL\\Validators\\UpdateVoteCategoryValidator")
@update
deleteVoteCategory(
id: ID! @whereKey
): VoteCategory
@delete
}
The UpdateVoteCategoryValidator
rules file:
public function rules(): array
{
return [
'id' => [
'required',
],
'name' => [
'required',
Rule::unique('vote_categories', 'name')->ignore($this->arg('id')), # add to the ignore() 2nd parameter if the field has a different name.
],
'active' => [
'required',
],
'meta_description' => [
'required',
],
'meta_keywords' => [
'required',
],
];
}
The CreateVoteCategoryValidator
rules file:
public function rules(): array
{
return [
'name' => [
'required',
Rule::unique('vote_categories', 'name'),
],
'active' => [
'required',
],
'meta_description' => [
'required',
],
'meta_keywords' => [
'required',
],
];
}