Development of Website Redirect Management System
A redirect management system allows configuring 301/302/307 redirects through a CMS interface without server configuration changes. Critical when restructuring a site, changing URL structure, or deleting pages.
Data Model
redirects (
id, from_path, to_url,
http_code: 301 | 302 | 307,
is_active,
hits, -- number of executions
last_hit_at, -- date of last execution
created_by, created_at, note
)
Middleware for Redirects
class HandleRedirects
{
public function handle(Request $request, Closure $next): Response
{
$path = '/' . ltrim($request->path(), '/');
$redirect = Cache::remember('redirect:' . md5($path), 3600, function () use ($path) {
return Redirect::where('from_path', $path)
->where('is_active', true)
->first(['to_url', 'http_code']);
});
if ($redirect) {
Redirect::where('from_path', $path)->increment('hits');
Redirect::where('from_path', $path)->update(['last_hit_at' => now()]);
return redirect($redirect->to_url, $redirect->http_code);
}
return $next($request);
}
}
Middleware is registered in bootstrap/app.php in the web group with high priority.
Import Redirects from CSV
When migrating a site, hundreds or thousands of redirects need to be loaded at once:
public function importFromCsv(UploadedFile $file): array
{
$rows = array_map('str_getcsv', file($file->getRealPath()));
$header = array_shift($rows); // first row — headers
$created = $skipped = $errors = 0;
foreach (array_chunk($rows, 500) as $chunk) {
$inserts = [];
foreach ($chunk as $row) {
$data = array_combine($header, $row);
if (empty($data['from']) || empty($data['to'])) { $errors++; continue; }
$inserts[] = [
'from_path' => '/' . ltrim($data['from'], '/'),
'to_url' => $data['to'],
'http_code' => $data['code'] ?? 301,
'is_active' => true,
'created_at' => now()
];
$created++;
}
Redirect::upsert($inserts, ['from_path'], ['to_url', 'http_code']);
}
return compact('created', 'skipped', 'errors');
}
Regular Expressions (Optional)
For complex patterns:
// Redirect with regex: /blog/2023/* → /news/*
$redirect = Redirect::where('from_path', 'LIKE', '/blog/%')
->where('is_regex', true)
->get();
foreach ($redirect as $r) {
if (preg_match($r->from_path, $path, $matches)) {
$to = preg_replace($r->from_path, $r->to_url, $path);
return redirect($to, $r->http_code);
}
}
Identifying Broken Links
Run periodically — check from_path of redirects for incoming links from other pages. Redirects without incoming links and no executions for 6 months are candidates for deletion.
Development timeline: 2–3 days for a system with CSV import, caching, and management interface.







