同じサイトの/old配下を/new配下へ移し、後ろのパスとクエリ文字列を残すコードです。サイトのhome URLがドメイン直下の場合に限定します。サブディレクトリ設置やドメイン全体の移転にはそのまま使いません。
転送する範囲
/old、/old/、/old/about/?x=1を対象とし、/olderや/newは対象外です。旧サイトのWordPressまで到達するGET・HEADリクエストにだけ適用します。静的ファイル、管理画面、REST APIまで転送する仕組みではありません。
function waza_moved_path($uri) {
if (!is_string($uri) || preg_match('/[\x00-\x20\x7f\\\\]/', $uri)) return '';
$parts = wp_parse_url($uri);
if (!$parts || isset($parts['host']) || isset($parts['scheme']) || isset($parts['fragment'])) return '';
$path = $parts['path'] ?? '';
if ($path !== '/old' && strpos($path, '/old/') !== 0) return '';
// 特殊なエンコードや親ディレクトリ表記は自動変換しない。
if (preg_match('/%(?:2f|5c|2e|0[ad])/i', $path) || preg_match('#(?:^|/)\.{1,2}(?:/|$)#', $path)) return '';
$target = '/new' . substr($path, 4);
if (isset($parts['query'])) $target .= '?' . $parts['query'];
return $target;
}
add_action('template_redirect', function () {
if (is_admin() || is_feed() || is_preview() || is_trackback()) return;
if (!in_array($_SERVER['REQUEST_METHOD'] ?? '', array('GET','HEAD'), true)) return;
if (defined('REST_REQUEST') && REST_REQUEST) return;
$target = waza_moved_path(wp_unslash($_SERVER['REQUEST_URI'] ?? ''));
if ($target === '') return;
// 同じサイトの /old を /new へ移す例。検証中は302。
if (wp_safe_redirect(home_url($target), 302, 'WAZA path redirect')) exit;
}, 1);
設置と確認
旧側の子テーマfunctions.phpなどへ追加します。開始タグは既存PHP内には追加しません。/oldと/newは例なので、移転元と移転先の対応を確認してコードを変更します。転送先が存在すること、末尾スラッシュ、クエリ文字列の扱い、対象外URL、リダイレクトループがないことを確認してください。クエリに秘密情報が含まれる運用には流用しません。
検証中は302です。恒久移転と確認できた場合に限り302を301へ変更します。301はブラウザーや中間キャッシュに残るため、戻す際はコード停止だけでなくキャッシュの影響も確認します。SEO効果や順位維持を保証しません。
実際のリクエストで転送範囲を確認する
| リクエストの例 | このコードの結果 |
|---|---|
| GET /old/?x=1 | 302。/new/?x=1へ転送 |
| HEAD /old/about/ | 302。/new/about/へ転送 |
| POST /old/ | このコードでは転送しない |
| GET /older/・/new/ | このコードでは転送しない |
| GET /wordpress/old/ | この例の/old配下ではないため転送しない |
転送先のページが存在するかは、この関数だけでは確認しません。
旧URLの302とLocationを確認した後、新URLを別に開いて内容とHTTPステータスを確認します。
対象外URLは転送を行わず、通常のWordPress処理へ戻るため、200か404かは元のサイト構成で変わります。
プラグイン・Webサーバーとの使い分け
Redirectionは外部URLも指定できます。また、WordPressを使っていること自体が.htaccessの転送を無効にするわけではありません。サーバー種類やルール順序で結果が変わります。個別URLの管理はRedirectionの設定例も参照してください。
掲載コードはWordPress 7.1.2の隔離環境で、実際のGET・HEADの302応答とLocation、POSTと対象外パスの非転送を確認しました。
本番サイトの転送設定は追加していません。
サブディレクトリ設置への対応を確認した結果ではないため、冒頭の適用範囲を守ります。
戻す場合は今回の関数とフック登録を外します。



