Advanced Controller Middleware in Laravel: Using the HasMiddleware Interface
Ever wished you could keep your middleware logic closer to your controllers? Laravel's HasMiddleware
interface brings a new, elegant way to assign middleware right in your controller classes. Let's explore this powerful feature!
Traditional Route Middleware
Traditionally, we've assigned middleware in our route files:
Route::get('/profile', [UserController::class, 'show'])->middleware('auth');
Enter HasMiddleware Interface
Now, Laravel offers a more organized approach. By implementing the HasMiddleware
interface, you can define middleware directly in your controller:
use App\Http\Controllers\Controller;
use Illuminate\Routing\Controllers\HasMiddleware;
use Illuminate\Routing\Controllers\Middleware;
class UserController extends Controller implements HasMiddleware
{
public static function middleware(): array
{
return [
'auth',
new Middleware('log', only: ['index']),
new Middleware('subscribed', except: ['store']),
];
}
}
Different Ways to Define Middleware
- Simple String Middleware:
'auth' // Applies to all controller actions
- Middleware with Constraints:
new Middleware('log', only: ['index']) // Only for index action
new Middleware('subscribed', except: ['store']) // All actions except store
- Inline Closure Middleware:
use Closure;
use Illuminate\Http\Request;
public static function middleware(): array
{
return [
function (Request $request, Closure $next) {
// Your middleware logic here
return $next($request);
}
];
}
Real-World Example
Here's a practical example of a controller that manages user subscriptions:
use App\Http\Controllers\Controller;
use Illuminate\Routing\Controllers\HasMiddleware;
use Illuminate\Routing\Controllers\Middleware;
use Illuminate\Http\Request;
use Closure;
class SubscriptionController extends Controller implements HasMiddleware
{
public static function middleware(): array
{
return [
'auth', // Ensure user is logged in
new Middleware('verified', only: ['upgrade', 'cancel']), // Email verified for important actions
new Middleware('subscribed', except: ['pricing', 'subscribe']), // Check subscription status
function (Request $request, Closure $next) {
if ($request->user()->onGracePeriod()) {
// Add grace period warning to response
$response = $next($request);
$response->with('warning', 'Your subscription is ending soon!');
return $response;
}
return $next($request);
}
];
}
public function upgrade()
{
// Upgrade subscription logic
}
public function cancel()
{
// Cancel subscription logic
}
}
Using the HasMiddleware
interface and keeping your middleware definitions in your controller classes can lead to cleaner, more maintainable code. It's especially useful for complex controllers that need different middleware rules for different actions.
If this guide was helpful to you, subscribe to my daily newsletter and give me a follow on X/Twitter. It helps a lot!