phplaravellaravel-11

Laravel Dependency Injection running before Middleware


I was under the impression that middleware runs BEFORE the route functions it wraps around.

Route::middleware([MyMiddleware::class])->group(function() {
  // routess
});

But if one of the routes has dependency injection (ie, PATCH function in a controller):

public function update(MyModel $model, Request $request) {}

If the MyModel does not exist, then it throws the error that it doesn't exist without running the middleware.

The workaround I have done is this in app.php which forces it to run before the functions:

$middleware->api(prepend: [MyMiddleware::class]);

Is this correct? I feel that this step shouldn't be necessary.

FYI I am using this type of middleware:

return $next($request);

Solution

  • Middleware can be run before or after the route. It really depends on your middleware code (please include that in your question).

    From the Laravel docs...

    Before

    <?php
    
    namespace App\Http\Middleware;
    
    use Closure;
    use Illuminate\Http\Request;
    use Symfony\Component\HttpFoundation\Response;
    
    class BeforeMiddleware
    
    {
        public function handle(Request $request, Closure $next): Response
    
        {
            // Perform action
    
            return $next($request);
        }
    }
    

    After

    <?php
    namespace App\Http\Middleware;
    
    use Closure;
    use Illuminate\Http\Request;
    use Symfony\Component\HttpFoundation\Response;
    
    class AfterMiddleware
    {
        public function handle(Request $request, Closure $next): Response
        {
            $response = $next($request);
    
            // Perform action
    
            return $response;
        }
    }
    

    Another possible reason:

    If you are using implicit binding in your route, I believe that will get resolved first. If the model isn't found, it won't even try to run the middleware. You could use optional parameters which will allow the route to be run even if it can't find the model:

    // routes/api.php
    Route::patch('/path/{model?}', [MyController::class, 'update']);
    
    // app/Http/Controllers/MyController.php
    public function update(?MyModel $model = null, Request $request) {}