There are several ways in which you can determine if a user owns an object in your Laravel application. This post will give you a couple of examples how you could implement this check within your form request validations.
An example use case
Let's take this example use case: a user creates an order and assigns it to a customer through a web form. However, one could abuse the form and alter the customer_id to a customer that doesn't belong to the current user.
Using findOrFail in your controller function
The simplest way to prevent this from happening is to lookup the customer on the user customers relation. This is assuming you have a hasMany relation on your User model for customers.
Now when the customer is not found, it will result in a 404 error. This is a solid way, but it doesn't provide feedback to the user and isn't handled within the validation rules. Let's look at how we could do that.
Using a Closure
If you need this sort of validation only once, you could implement this in your validation using a Closure. That would look like this:
request()->validate([
'customer_id' => [
'required',
function ($attribute, $value, $fail) {
if (auth()->user()->customers()->where('customers.id', $value)->doesntExist()) {
$fail($attribute.' does not belong to you.');
}
},
]
]);
Using a custom validation rule
Now if you need this sort of check multiple times throughout your application, you could best make use of a Rule object. You can create one by running the following artisan command.
php artisan make:rule Ownership
This class will be created within your app/Rules directory. In this example, the Ownership rule will accept a model (string or instance) as parameter. Then we will try and find that instance of the model and check if the model's user_id is the same as the current user's id.
Sometimes you might not use the user_id column but maybe something like owner_id. You could make that changeable by adding an additional parameter for this column name to the constructor.
Now to implement this in your validation rules, you can do the following:
I think all options are fine and there might even be betters solutions. If you use one of the solutions in this post, the one you should use depends on whether you would want to display a validation message and if you find yourself doing this type of check multiple times.