phplaravelmiddlewarelaravel-middlewaretwill

404 URLs does not pass through web Middlewares in Laravel 11, php8.2 and TwillCMS


I have a redirect middleware. This middleware checks if the path is defined in our Redirection module table.

Normally, when a page exists (200) say http://localhost/existing-page, I can redirect the page to any url I want.

However any url that resolves to (404), does not pass through this middleware hence the rediretions does not work.

I tried following:

  1. Add redirect middleware to 'web' middleware group in app.php under bootstrap. 404 URLs did not pass trough eventhough all existing routes including Twill's admin routes did:
        $middleware->group('web', [
            ...
            \App\Http\Middleware\Redirector::class
        ]);
  1. I defined a Route::fallback()inside my web.php, outside my standart route groups and as the last and the first route declaration inside the file, did not pass through.
Route::fallback(function () {
    dd('404');
    return view("404"); // template should exists
})->middleware('redirect');

Keep in mind that my dynamic route handlers defined as follows in their controllers:

   public function show(Page $page): View|RedirectResponse
   {
     ...
   }

I think my knowledge on Laravel's exception handlers and Middlewares is insufficient. Any help is appriciated.


Solution

  • So I have found what the problem is.

    Basically, I was registering my Redirection middleware only in the routes/web.php which is actually at the end of the lifecycle. However, I use Route Model Binding for aforementioned system. and group them as follows:

    Route::group([
        'prefix' => LaravelLocalization::setLocale(),
        'middleware' => ['redirect','noIndexNoFollow','localize',  'localizationRedirect', 'localeViewPath'],
    ], function () {
        #Route Declarations
    });
    

    Then I found out that there was a group of Middleware that I was not able to see in bootstrap/app.php One of them being \Illuminate\Routing\Middleware\SubstituteBindings::class. This Middleware basically makes the connection between a slug / ID with It's respective Model. Since this random URLs have no record in database, The Middleware fires 404 Exception. Which blocks request flow to the aforementioned group and it's Middlewares.

    So what I did was as mentioned in Laravel's documentation added these default Middlewares to my bootstrap/app.php and added the Redirection Middleware before SubstituteBindings Middleware as follows:

    <?php
    
    ...
        ->withMiddleware(callback: function (Middleware $middleware) {
            $middleware->group('web', [
    
                \Illuminate\Cookie\Middleware\EncryptCookies::class,
                \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
                \Illuminate\Session\Middleware\StartSession::class,
                \Illuminate\View\Middleware\ShareErrorsFromSession::class,
                \Illuminate\Foundation\Http\Middleware\ValidateCsrfToken::class,
                **Redirector::class,**
                \Illuminate\Routing\Middleware\SubstituteBindings::class, // this allow Laravel to binde slugs / ids etc. to their respoective models in the controllers.
                // \Illuminate\Session\Middleware\AuthenticateSession::class,
            ]);
    ...
    

    After that it worked like a charm.