Take a look at this code example:
// relevant rules from the form request
'emails.*' => [
'bail',
'required',
'email',
'distinct',
Rule::exists('users', 'email')->whereNot('id', $this->user()->id),
]
// code in the controller action
$validated = $request->validated();
foreach ($validated['emails'] as $email) {
$user = User::where('email', $email)->firstOrFail();
// do something with each $user
}
Does anything look redundant to you?
Notice how the validation rule requires the email to exist in the users
table.
So why then also use firstOrFail()
in the controller?
We know the user must exist if it got past the request validation.
In this case, it's not that we expect it to throw a ModelNotFoundException
.
We know that can never happen.
But by using firstOrFail()
, we are now narrowing the type of $user
from ?User
to User
.
This means that further uses of $user
inside this loop don't have to handle the possibility of it being null
.
It simplifies our code and satisfies static analysis tooling.
And as a bonus, we get the added protection of the additional check, just in case validation rules change in the future.
Here to help,
Joel
P.S. How do you know how far to go with static analysis in your project? We can help strike the balance between safety and not introducing too much friction.