PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC] ); echo "=== sys_redirect rows for /events (and children) ===\n"; $rows = $pdo->query( "SELECT uid, deleted, source_host, source_path, target, target_statuscode, createdon, creation_type FROM sys_redirect WHERE source_path LIKE '/events%' ORDER BY uid" )->fetchAll(); foreach ($rows as $r) { echo sprintf(" #%-5d del=%d %s %s -> %s [%d] creation_type=%s created=%s\n", $r['uid'], $r['deleted'], $r['source_host'], $r['source_path'], $r['target'], $r['target_statuscode'], (string)($r['creation_type'] ?? '?'), date('Y-m-d H:i', (int)$r['createdon'])); } if ($rows === []) { exit(" none - nothing to fix.\n"); } $live = array_values(array_filter($rows, fn(array $r): bool => (int)$r['deleted'] === 0 && $r['source_path'] === '/events')); if (count($live) === 0) { exit("\nNo live /events row - check manually.\n"); } // keep the command's own row (source_host '*', target t3://page) as 301, // delete every other live /events row $keep = null; foreach ($live as $r) { if ($r['source_host'] === '*' && str_starts_with((string)$r['target'], 't3://page')) { $keep = $r; break; } } $keep ??= $live[0]; echo "\nPlan: keep #{$keep['uid']} (force 301), delete " . (count($live) - 1) . " other live row(s)\n"; if (!$apply) { exit("DRY RUN - add --apply to write.\n"); } $pdo->prepare('UPDATE sys_redirect SET target_statuscode = 301 WHERE uid = ?')->execute([(int)$keep['uid']]); foreach ($live as $r) { if ((int)$r['uid'] !== (int)$keep['uid']) { $pdo->prepare('UPDATE sys_redirect SET deleted = 1 WHERE uid = ?')->execute([(int)$r['uid']]); echo " deleted #{$r['uid']}\n"; } } echo "Done. Flush the cache (redirects are cached), then re-test /events.\n";