skip to Main Content

I read here that in Laravel we can use the can method instead of the traditional middleware call on a route. https://laravel.com/docs/11.x/authorization#middleware-actions-that-dont-require-models

use AppModelsPost;
 
Route::post('/post', function () {
    // The current user may create posts...
})->can('create', Post::class);

Now the traditional method for middlewares looks like this:

Route::post('/post', function () {
    // The current user may create posts...
})->middleware('can:create,AppModelsPost');

I really like this can method and it would be nice to be able to replace middleware calls for update too to be consequent:

use AppModelsPost;
Route::put('/post/{post}', function (Post $post) {
    // The current user may update the post...
})->middleware('can:update,post');

Is there a way to do this? The documentation does not contain anything about this…

2

Answers


  1. Using the can Method for Update Routes

    use AppModelsPost;
    
    Route::put('/post/{post}', function (Post $post) {
        // The current user may update the post...
    })->can('update', 'post');
    

    ->can('update', 'post'): Specifies the authorization policy to be applied. Here, 'update' is the policy method, and 'post' is the parameter passed to that method. Laravel will automatically inject the model instance from the route parameter and perform the authorization check.

    In your PostPolicy, you should have a method like this:

    public function update(User $user, Post $post)
    {
        // Authorization logic to determine if the user can update the post
        return $user->id === $post->user_id;
    }
    
    Login or Signup to reply.
  2. There are few steps you need to follow.

    Create & get registered your Policy class.

    With this command create a Policy-class. The generated policy will be placed
    in the app/Policies directory.

    php artisan make:policy PostPolicy --model=Post
    

    This class look like this.

    namespace AppPolicies;
    
    use AppModelsPost;
    use AppModelsUser;
    
    class PostPolicy
    {
        /**
         * Determine whether the user can update the post.
         *
         * @param  AppModelsUser  $user
         * @param  AppModelsPost  $post
         * @return mixed
         */
        public function update(User $user, Post $post)
        {
            // Example: Only allow the user to update their own post
            return $user->id === $post->user_id;
        }
    }
    

    Then register the policy-class to the boot method of your application’s AppServiceProvider like this.

    use AppModelsPost;
    use AppPoliciesPostPolicy;
    use IlluminateSupportFacadesGate;
     
    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        Gate::policy(Order::class, OrderPolicy::class);
    }
    

    And finally you can use the can in the route to use this PostPolicy class like this.

    use AppModelsPost;
    
    Route::put('/post/{post}', function (Post $post) {
        // The current user may update the post...
    })->can('update','post'); //here `post` is an instance of `AppModelsPost` model
    

    N:B :-

    1. The Post model must have a foreign-key named user_id upon which update authorization will be matched.If no matched users found then an HTTP response with a 403 status will be returned.
    2. For more information check the official docs about how to create & registered Policy
    3. Check the Generating Policies & Registering Policies section of the docs.
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search