Laravel Advanced Redirects In Routes

You can use your routes file in Laravel to handle 301 redirects. Including 301 redirects, 302 redirects and wildcard redirects.

Mike Griffiths

When it comes to redirects people often look at the .htaccess file, assuming you're using Apache, or the equivalent on nginx. Although that's quicker, because it will redirect the user before spinning up an instance of your app, it's not necessarily better.

Putting your redirects in the app itself adds tones more flexibility. It allows you to put the redirects in version control (which can arguably be the case with the .htaccess method too, admittedly), but it also lets you do all sorts of fancy stuff, like loading redirects from a database, building an interface for your client, SEO manager, or even yourself to manage them.

I recently migrated my blog to a new platform. I no longer (by choice) have /blog prefixed to my posts. A few of my posts get a lot of search traffic so to prevent them 404ing I decided to redirect everything to the relevant post. Fortunately all of the slugs remain the same, so I was able to do the following in my routes.php file.

use Illuminate\Support\Facades\Request;

Route::redirect('blog/{any}', url(Request::segment(2)), 301);

Let's dissect that a little...

blog/{any} matches any URL with 2 segments that begins with 'blog'. For example blog/laravels-forcefill-and-forcecreate would match, but contact/me would not.

url(Request::segment(2)) this creates a full URL using my apps settings based on the second segment in the request. Using the same example, the value of Request::segment(2) is laravels-forcefill-and-forcecreate.

Lastly we've got 301. This just tells Laravel to make it a 301 redirect. A 301 is a permanent change, opposed to a 302 which is seen as temporary. Really, this just tells the search engines to update their index with the new URL.

The second parameter also accepts a closure, so you can do all sorts of fancy stuff, or pass it to a controller to do even more.

use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Str;

Route::redirect('blog/{any}', function($segment) {
    $blog = \App\Blog::findBySlug($segment);
    return url(Str::slug($blog->name));
}, 301);