Middleware is probably the better solution.
Catch-all routes work, but there are unintended consequences. You will have to manually handle 404 errors. You may also notice decreased performance depending on how your routes are setup.
Unlike catch-all routes, middleware can run before any routes are matched. Middleware can also be attached to a group of routes or a specific route. There are other middleware classes that are running by default, such as Authentication and CORS.
Here are the latest docs for middleware. Middleware hasn't changed much since Laravel 5, but the latest docs just explain the concept better. https://laravel.com/docs/7.x/middleware
Here is how you could use middleware to solve your problem.
Create a middleware class.
php artisan make:middleware My301Filter
If you want the middleware to run on all requests, register the class in app/http/kernel.php
protected $middleware = [
// ...
\App\Http\Middleware\My301Filter::class
];
Then you can parse your route using any way you want. Use logic to determine if a 301 should be called or if the app should continue. The $next
closure will go to the next middleware or route.
I chose to write something like this in my middleware class. However, this code is not perfect and you will probably have to change it to fit your needs.
<?php
namespace App\Http\Middleware;
use Closure;
class My301Filter
{
// ...
public function handle($request, Closure $next)
{
$needles = ["page=1", "index.php", "?&"];
foreach ($needles as $needle) {
if (strpos($request->getRequestUri(), $needle) !== false) {
return redirect('/some/route', 301);
}
}
return $next($request);
}
}