WordPressでコーポレーションサイトを運営している企業さんが、サイトの全面リニューアルに際しURL最適化を行った所「困った事になった」と相談に来ました。
要約すると

ブログ記事のURLを301リダイレクトしたいけど、数が多すぎて無理だから助けて欲しい!
って感じの内容。
なるほど?取りあえず伺いましょう。
状況を見る
サイト開設時に設定したパーマリンクのルールを変更したら、インデックスされている記事URLが全部404になっちゃったよーと。
変更後:/%category%/%postname%/
ひとまず今の状況を説明してもらうと、

動的には出来ないと言われたから.htaccessファイルに力技で列挙しています!
との事で、中々香ばしい感じの.htaccessファイルを見せて貰いました。
直近半年でアクセス数の多い記事のトップ50を列挙したらしいのですが、site:[サイトURL]でGoogle検索をかけて、インデックスを出した時に「旧URLの記事がビッシリ表示される」のを何とかしてほしい、なんならインデックスから削除してくれも構わないとの事。
なるほど、話が見えてきましたね。

サイトリニューアルをして新しいサイトマップを送信したから、インデックス済みの旧サイトのURLを綺麗にして欲しい!
こう言う事ね。
全部救済してしまっても構わんのだろう?
ひとまず持ち帰って記事総数を調べて見ると、公開済みの記事だけで2,600件ぐらい。
依頼内容的には「人気記事以外のインデックは消えても良いから綺麗にして」との事でしたが、生かすにせよ殺すにせよ手作業でやる量じゃない事は明らかです。
恐らく「動的には出来ない」って言った人は、mod_rewriteでは動的に出来ませんよって意味だったんじゃないかな?
解決策を考える
パーマリンクが変わったところで、スラッグは同じなんだから404ページのテンプレートをこちょこちょしたら解決するでしょってお話になりそうです。
念のため404になる旧URLを踏んで「アドレスバーにスラッグが表示されている」事を確認、こりゃ問題無さそうです。
- 404ページのド頭で、アドレスからスラッグと思われる部分を抜き出す。
- get_postsにスラッグと思われるものをパラメータに指定してリクエスト。
- 結果が返ってくれば旧URLなのでリダイレクトする。
- 結果が返って来なければそのまま404ページを表示する。
この作戦で行けるんじゃないかろうか。
解決コード
実際のソースに書き込んだ箇所を抜粋。
コーポレートサイト専用の自作テンプレートだったので404.phpに直書きしたけど、pre_get_postsとかにフックした方がスマートかもね。
<?php /** * The template for displaying 404 pages (Not Found). */ // 旧ブログURLかどうか調べる $args = [ "name" => substr(urldecode($_SERVER["REQUEST_URI"]), 1), "post_type" => "post", "post_status" => "publish", "numberposts" => 1 ]; if($blog = get_posts($args)) { header("HTTP/1.1 301 Moved Permanently"); header("Location: ".get_permalink($blog[0]->ID)); exit(); } get_header(); ?> (以下略)
結論から言うと「インデックスから旧URLが消えた訳ではない」ので、受注した要件は満たせていません。
しかしこれらの旧URLが踏まれた時は、自動的に301リダイレクトがかかってジワジワ更新されて行くハズなので、最も良い解決法に至ったのでは無いかと思います。
コード解説
リダイレクトをかけた時は、それ以降の処理が絶対に実行されないようにするため、必ずexit()を書いておきましょう。(Line:17)
PHPのheader関数は全ての出力前に実行される必要があるため、get_header()より前に判定処理を突っ込む必要があります。(Line:20)
あとがき
これにて解決、結果的に全ての記事のインデックスを失わずに済んだので大変喜ばれました。
コメント