13.x documentation and the Framework v13.36.0 implementation. For how to write regular middleware, see Middleware.
Separate registration, application, and execution
Router::aliasMiddleware() registers an entry in the Router’s array, with the alias as the key and the class name as the value. It does not instantiate the middleware or apply it to any route.
Alias names are part of your public API. Avoid built-in names such as
auth and throttle, as well as generic names likely to collide with other packages, and add a package-specific prefix. If you register the same key again, aliasMiddleware() overwrites the previous mapping.
Expose the alias from the provider
The following example creates middleware that adds a fixed identification header to the response. It is not an example of authentication, authorization, or access control. It assumes that Composer’s PSR-4 mapsAcme\Courier\ to src/ and that the provider is registered through auto-discovery or manually.
src/Http/Middleware/AddCourierHeader.php
boot(). Because boot() arguments are injected from the service container, you do not need to automatically edit the consumer’s bootstrap/app.php to register middleware.
src/CourierServiceProvider.php
Consumers apply it per route
In the consuming application’sroutes/web.php, assign it only to the routes that need it.
routes/web.php
->middleware(AddCourierHeader::class). Choose based on whether you need to offer consumers a short name.
When the package itself provides routes, also declare the required middleware explicitly in the route file. loadRoutesFrom() does not automatically add web or api. For registration methods and how route caching is handled, see Package route registration and caching.
Let consumers choose application-wide application
If consumers want to apply the middleware to everyweb route in their application, they add the following configuration to their existing withMiddleware() callback. This example does not replace the existing configuration.
web group, not the global stack. It is not automatically applied to api routes or to routes that have neither group.
Router group operations behave differently
If your package provides its own group, use a unique name. The following example goes inside the provider’sboot(Router $router).
->middleware('acme-courier'). However, this group contains only the classes you specify; it does not inherit the session or CSRF protection from web.
There are also APIs for adding to existing groups, but the v13.36.0 Router implementation has the following differences.
If you set only your package’s class with
middlewareGroup('web', [...]), you replace the existing contents of web. Do not confuse it with the methods for adding. Also, calling pushMiddlewareToGroup() on a nonexistent web group does not restore the standard web group.
The duplicate check in the adding methods compares the registered values. An alias and a class name that point to the same class are different strings, so they are separate items at the registration stage. Use consistent notation, and do not assume that the same class written in different forms will be deduplicated at registration time.
Registration order alone does not guarantee execution order
The Router expands the aliases and groups assigned to a route, processes exclusions, and then sorts by priority. Prepending or appending alone does not guarantee a strict ordering relative to authentication or route model binding. In addition, the HTTP Kernel’ssyncMiddlewareToRouter() synchronizes the Kernel’s groups to the Router using middlewareGroup(). If the Kernel’s configuration is resynchronized later, the contents of groups you added to the Router directly may be replaced. Rather than competing to modify existing groups based on the boot order of packages, the basic approach is to consolidate configuration in the consuming application’s withMiddleware().
For features that require a particular order, such as after the session starts or after authentication, document that requirement in the installation instructions and verify it together with the consuming application’s priority settings. Avoid having a package replace the application’s entire priority list.
The boundary between caching and verification
Do not place alias registration inside aroutesAreCached() condition or in a route file. loadRoutesFrom() does not load the route file when a cache exists, but registration is still needed to resolve aliases that remain in cached routes at runtime. Register them every time in the provider’s boot().
If you change route assignments, rebuild the route cache in the consuming application.
-vv to expand and check group contents. However, a successful listing does not guarantee the processing inside the middleware or the use of sessions. You also need HTTP request tests.
The following method is added to a Feature test in a Laravel application that defines the /courier-status route above.
Unit tests that check whether a group exists or inspect the alias array are a separate kind of verification from actual HTTP execution. In particular, verify caching not just by inspecting the Router in the same process, but with a fresh boot after the cache is created. If you use long-running workers, reload them according to your normal deployment procedure.
Related pages
Middleware
Review the basics of creating middleware, applying it to routes, parameters, and priority.
Package route registration and caching
Review how route loading relates to configuration when the cache is created.