Creating Simple HTTP Redirect Routes from a Statamic Site

November 29, 2023 —John Koster

I've recently been working on consolidating a number of websites. A common task when doing so is ensuring that all existing paths on separate domains are correctly redirecting to their new home.

There are dedicated services that can handle these types of redirects, but I was looking for something quick and simple to handle these redirects; in this post I'll walk you through the quick method I came up with for generating a routes file from an existing Statamic site.

The sites I am consolidating are fairly simple, and I only need to point to similar URLs on the new domain.

#Gathering the Entries and URLs

To get started, I needed to fetch the relative URLs for all of my existing Statamic entries and build up a list of all the relative URLs. Luckily, Statamic makes this painless and provides a simple way to retrieve them using the Statamic\Facades\Entry facade:

1<?php
2 
3use Statamic\Facades\Entry;
4 
5function generateRedirectRoutes(string $homeRedirect, string $basePath, string $notFoundRedirect): string
6{
7 $pathParts = [];
8 
9 foreach (Entry::all() as $entry) {
10 $url = $entry->url();
11 
12 // Skip the home page.
13 if ($url == '/') {
14 continue;
15 }
16 
17 $pathParts[] = " '{$url}',";
18 }
19 
20 $paths = implode("\n", $pathParts);
21 
22 // We'll finish this later.
23}

at this point, our $paths variable would contain a value similar to the following:

1
2 '/home',
3 '/about',
4 '/contact',

the leading whitespace is just there to make things look a little bit better in the final output.

#Creating the Redirects

At this point I have my relative URLs in a nicely formatted string, and all that is left to do is generate the routes file. I will be doing this by constructing a string with interpolated values and returning it:

1<?php
2 
3function generateRedirectRoutes(string $homeRedirect, string $basePath, string $notFoundRedirect): string
4{
5 $pathParts = [];
6 
7 foreach (Entry::all() as $entry) {
8 $url = $entry->url();
9 
10 // Skip the home page.
11 if ($url == '/') {
12 continue;
13 }
14 
15 $pathParts[] = " '{$url}',";
16 }
17 
18 $paths = implode("\n", $pathParts);
19 
20 return <<<EOT
21<?php
22 
23use Illuminate\Support\Facades\Route;
24 
25Route::get('/', function () {
26 return redirect()->to('{$homeRedirect}', 301);
27});
28 
29Route::get('/{any}', function (\$any) {
30 
31 \$paths = [
32{$paths}
33 ];
34 
35 if (! in_array(\$any, \$paths)) {
36 return redirect()->to('{$notFoundRedirect}', 301);
37 }
38 
39 return redirect()->to('{$basePath}'.\$any, 301);
40})->where('any', '.*');
41EOT;
42}

Our function now looks pretty complicated, but its really just creating a fairly typical Laravel routes file with the information we provided it. Using the same three sample URLs from earlier, if we were to call our new function like so:

1<?php
2 
3generateRedirectRoutes('https://example.org', 'https://example.org/my-prefix', 'https://example.org/404');

it would generate the following routes file for us:

1<?php
2 
3use Illuminate\Support\Facades\Route;
4 
5Route::get('/', function () {
6 return redirect()->to('https://example.org', 301);
7});
8 
9Route::get('/{any}', function ($any) {
10 
11 $paths = [
12 '/home',
13 '/about',
14 '/contact',
15 ];
16 
17 if (! in_array($any, $paths)) {
18 return redirect()->to('https://example.org/404', 301);
19 }
20 
21 return redirect()->to('https://example.org/my-prefix'.$any, 301);
22})->where('any', '.*');

#Wrapping Up

It's a rather quick and simple way to generate a routes file, but it works for my use case. If you are looking to do something similar, you could expand on the logic to handle more complicated redirects as needed.

Some absolutely amazing
people

The following amazing people help support this site and my open source projects ♥️
If you're interesting in supporting my work and want to show up on this list, check out my GitHub Sponsors Profile.