Exists
Rule to Avoid N+1
Query Issue in Array Validation
#53420
Unanswered
Jagadish056
asked this question in
Q&A
Replies: 2 comments 9 replies
-
Have you tried creating a custom rule? |
Beta Was this translation helpful? Give feedback.
9 replies
-
@Jagadish056 Just as @macropay-solutions suggested, you can create a custom object rule that will do what you want in the laravel way. <?php
namespace App\Rules;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
class ExistUserId implements ValidationRule
{
/**
* Run the validation rule.
*/
public function validate(string $attribute, mixed $value, Closure $fail): void
{
if (null === $value)) {
return;
}
if (!is_array($value) || [] === $value) {
$fail('The :attribute must be array not empty.');
return; // I am not sure if fail closure will throw or not.
}
if ($value !== \array_filter($value, fn (mixed $value): bool => is_int($value))) {
$fail('The :attribute array must contains only integers.');
return; // I am not sure if fail closure will throw or not.
}
if (Users::query()->whereIn('id', $values)->count() !== count(array_unique($values))) {
$fail('The :attribute array must contains only valid user ids.');
}
}
}
public function rules(): array
{
return [
'id' => [new ExistUserId()],
];
} https://laravel.com/docs/11.x/validation#using-rule-objects The above is valid for L >=9 For 8 https://laravel.com/docs/8.x/validation#using-rule-objects you would need 'bail' + as many rules as messages. |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
I'm trying to validate an array of
id
values in a Laravel form request, but I want theexists
check to happen only after all other validation rules have passed. This way, I can ensure that database queries for theexists
validation are executed last, which should help improve efficiency.Here’s my current
rules()
method:The problem with this approach is that it creates an
N+1
query issue, as eachid
in the array triggers a separateexists
query. To optimize this, I want to defer theexists
check to the end of the validation process, so I can perform a single database query for allid
values at once.My idea is to initially validate each
id
as an integer, then perform theexists
check at the end, like this:To handle this, I’m considering using an
after()
hook in the form request to check allid
values together, ensuring a single database query only if all other rules are pass.Is there a way in Laravel to delay the
exists
validation rule like this?Or, is there a more efficient approach to avoid the N+1 query issue?
Beta Was this translation helpful? Give feedback.
All reactions