nicknds97's avatar

Add middleware to package routes

Suppose I installed some packages xyz. The xyz package has some routes registered and I need to add middleware to those routes. How can I achieve that?

0 likes
5 replies
LaryAI's avatar
Level 58

One way to achieve this is by creating a service provider for the package and registering the middleware in the boot method. Here's an example:

  1. Create a service provider for the package by running the following command:
php artisan make:provider XyzServiceProvider
  1. In the boot method of the XyzServiceProvider, register the middleware for the package routes:
use Illuminate\Support\Facades\Route;

public function boot()
{
    Route::middleware(['middleware-name'])->group(function () {
        $this->loadRoutesFrom(__DIR__.'/path/to/routes/file.php');
    });
}
  1. In the register method of the XyzServiceProvider, register the package routes:
public function register()
{
    $this->loadRoutesFrom(__DIR__.'/path/to/routes/file.php');
}
  1. Finally, register the XyzServiceProvider in the config/app.php file:
'providers' => [
    // ...
    App\Providers\XyzServiceProvider::class,
],

This will load the package routes with the specified middleware applied to them.

nicknds97's avatar

@LaryAI Yes, this will work. But what if the package changes the route path in the next update? Then we would have to update the Service Provider as well. Is there any other solution to the above problem?

erythro's avatar

@nicknds97 coming to this late, but I would pass a closure to the booted method in your service provider that gets the Illuminate\Routing\Router instance from the container, finds the routes there (either by name or from the uri whichever you feel is more stable between releases) and attach the middleware to the Illuminate\Routing\Route instance there

public function boot(): void
{
    $this->booted($this->addMiddlewareToVendorRoute(...));
}

public function addMiddlewareToVendorRoute(): void
{
    /** @var Route $route */
    $route = $this->app
        ->get(Router::class)
        ->getRoutes()
        ->getByName('vendor.routename') 
            ?? throw new \RuntimeException('Route "vendor.routename" not found');
    $route->middleware(MyMiddlewareForVendor::class);
}

jaseofspades88's avatar

Two viable options:

  • Some packages allow you to publish their routes. You can do this and then add your middleware to the published route files.
  • Copy their route implementation and the controller to which they point, add it to your route file and then add the middleware to the overridden route definition.
Ken-vdE's avatar

You can add this to your AppServiceProvider::boot():

        /** {@see Router::dispatchToRoute()}. */
        \Route::matched(function(RouteMatched $event) {
            if ($event->route->getName() === 'the.route.name') {
                $event->route->middleware('whatever-extra-middleware');
            }
        });

You could also use $event->route->named('something.with.wildcard.*') or other neat stuff (checkout vendor/laravel/framework/src/Illuminate/Routing/Route.php).

Please or to participate in this conversation.