Search code examples
phplaraveleloquentlaravel-11

Laravel UpdateUserRequest validation rule with user id


I have a User model, and this is my update() method in UserController:

public function update(Request $request, User $user)
{
    // Assign authorization
    Gate::authorize('update', $user);
    
    $request->validate([
        'username' => 'required|unique:users,username,' . $user->id,
        // other rules ...
    ]);
    
    // ...
}

I want to keep these validation rules in a separate UpdateUserRequest request:

class UpdateUserRequest extends FormRequest
{
    public function authorize(): bool
    {
        return true; // Changed to 'true' to handle authorization logic in UserPolicy
    }

    public function rules(): array
    {
        return [
            'username' => 'required|unique:users,username,' . $user->id, // <-- Problem
            // other rules ...
        ];
    }
}

The problem here is that $user is not defined. I have read elsewhere that using a route for this matter is a possible solution, but that's not the proper way of achieving this task.

My question is what is the correct way to pass user information to UpdateUserRequest class?


Solution

  • My question is what is the correct way to pass user information to UpdateUserRequest class?

    I assumed you are using laravel 11.X and your route definition is...

    Route::put('/users/{user}', [UserController::class, 'update']);
    

    In this scenario you can do it inside the UpdateUserRequest.

    class UpdateUserRequest extends FormRequest
    {
        public function authorize(): bool
        {
            // Here you can also interact with your `gates` & `policy`,Check the docs link I provided below to get clear insights.
            return true; 
        }
    
        public function rules(): array
        {
            //Scenario 1
            $user = User::find($this->route('user')); //If you are not using `implicit model binding`
            //Scenario 2
            $user = $this->user ; //If you are using `route-model-binding`
    
    
            return [
                'username' => 'required|unique:users,username,' . $user->id, // <-- "Issue will be solved"
                // other rules ...
            ];
        }
    }
    

    Then in Controller class import & type-hint the FormRequest class i.e. UpdateUserRequest on your Controller method that is missing in your current code.

    public function update(UpdateUserRequest $request, User $user)
    {
        // Assign authorization
        Gate::authorize('update', $user);
    
        // Retrieve the validated input data...
         $validated = $request->validated();  // it will by default validate all the input data you set up in the `rule()` of `UpdateUserRequest`
        
        
        // ...
    }
    

    For more clear and in-depth insights please check the official-docs here.