Using the new Laravel missing
function to prevent link rot
Taylor Otwell recently introduced a new route helper function, eloquently named missing
.
Using the new method it is possible to catch ModelNotFoundException
s and change the default 404 behavior to something more suitable.
You can read more about the new function on the Laravel docs: Customizing missing model behavior.
Preventing link rot when changing slugs
Let's assume we recently published a new blog post. It's actively being linked to, it's getting shared on Twitter, everything is great. However, what if we need to change the existing slug? All those links are going to be broken.
Here's what I came up with to prevent this:
Route::get('blog/{post}', [PostController::class, 'show'])->name('posts.show') ->missing(function (\Illuminate\Http\Request $request) { return Redirect::fromRequest($request); // Note: NOT the Redirect facade });
Whenever a slug cannot be found, I forward the request to a custom Redirect
model to handle the request.
This is what the Redirect
model looks like:
<?php namespace App; use Illuminate\Database\Eloquent\Model; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; class Redirect extends Model { public $timestamps = false; public function post() { return $this->belongsTo(Post::class); } public static function fromRequest(Request $request): RedirectResponse { $slug = $request->route()->parameter('post'); $redirect = static::with('post')->where('slug', $slug)->first(); // No redirect was found if ($redirect === null) { abort(404); } // A redirect with an unpublished post was found if ($redirect->post === null) { abort(404); } return redirect()->route('posts.show', $redirect->post); } }
Let's demystify the code snippet by having a closer look at the fromRequest
method:
First, I grab the value of the post
parameter from the route I defined earlier.
Then I check in the database whether a redirect for this slug exists. When checking, I already eager load the related post to prevent unnecessary database queries.
Now the only thing that is left to do, is check whether a 'redirect' and its related post were found and to return a redirect response accordingly.
Conclusion
By adding old slugs to the redirects table and utilizing the missing
method in combination with the fromRequest
method we can prevent link rot by redirecting outdated links to the correct location.