wordpressで301リダイレクトをする方法

wordpressでリダイレクトするには、functions.phpかプラグイン、.htaccessにコードを書き込む方法が考えられます。一般には.htaccessを弄る方がよく知られていますが、wordpressで301リダイレクトを行うこともできます。

301リダイレクトとは?

301はステータスコードの一つで、恒久的に移動したことを意味します。恒久的とは永久に変わらないということです。これによく似たもので302もありますが、こちらは一時的に移動した時に使われます。このうち検索エンジンに対しては基本的に301リダイレクトを使うのが一般的です。

wordpressの自動リダイレクト

wordpressでは、スラッグを変更するとデータベースのwp_postmetaテーブルに保存され、旧URLにアクセスすると新URLへ自動的に301リダイレクトします。この変更は、wp_postmetaテーブル内でmeta_keyカラムの「_wp_old_slug」として登録されます。同テーブル内のmeta_valueには、古いほうのスラッグ名が格納されています。

また、wordpressで行われる自動リダイレクトは、上記データがなければ左側の文字からアルファベット順などで自動的に選択するようになっています。従って、この場合のリダイレクトは意図した記事と異なる記事へ転送されることもあります。下記の方法で設定すると、この自動処理の影響を受けません。

wordpressで301リダイレクトする方法

以下のようなコードをwordpressテーマテンプレートのheader.phpに記入します。$urlは配列になっており、左側のhttps://example.com/1/から右側のhttps://example.com/2/へリダイレクトするという意味になります。

$url=['https://example.com/1/' => 'https://example.com/2/'];
if(!empty(get_the_permalink()) && array_key_exists(get_the_permalink(),$url)){
foreach($url as $key => $val){
if(get_the_permalink()==$key){
header("Location: ".$val, true, 301);
exit;
}
}
}

.htaccessで301指定

以下のコードをドメイン直下のディレクトリに「.htaccess」ファイルとして保存します。ドメイン直下とは「https://example.com/.htaccess」という形式になります。

ページ単位で指定

RewriteEngine on
RewriteRule ^old-page.html$ http://example.com/new-page.html [R=301,L]

ディレクトリ単位で指定

RewriteEngine on
RewriteRule ^old-directory(.*)$ /new-directory$1 [R=301,L]

ドメイン単位で指定

RewriteEngine On
RewriteCond %{http_host} ^old-example.com
RewriteRule ^(.*) http://new-example.com/$1 [R=301,L]

wordpressと.htaccessにおける設定の違い

wordpressでの設定も.htaccessでの設定も、同じ結果を返します。違いは処理のどこで301リダイレクトを指定するかと、頻繁に指定を繰り返す場合の管理面の煩わしさとなります。一度決めたらほとんど変更や追加することがないのであれば、後者のほうが管理が楽になります。反対にしょっちゅう追加や変更をするのであれば、ワードプレスで直接弄れるようにした方が管理が楽となります。

ただし、ワードプレステーマのheader.phpに上記コードを記述した場合、テーマを変更すると設定も消えます。そのため、テーマの変更も定期的に行う予定があるのであれば、上記コードをプラグイン化したほうが効率もよくなります。より管理しやすくするためには、ワードプレスの管理画面上からURLをデータベースへ登録できるようにすると良いかも知れません。

プラグイン化

まず下のような感じのコードを記述したファイルを作ります。そして適当な名前をつけたフォルダを作成し、そこに作ったファイルを入れます。これをワードプレスの「wp-content/plugins/」ディレクトリにアップロードします。次いでワープレのプラグイン管理画面からこのプラグインを有効化すると動作するようになります。Plugin NameのAAAは何でも構いません。

こちらはheader.phpに記述したものと異なり、get_headerフック内に上記のコードを入れています。これは中身を直接プラグインのファイルに記述しても動作しないためです。また、functions.phpに記述しても動作しますが、その場合テーマを変更すると動かなくなります。

get_headerフックは、header.phpを読込む前に何らかの処理をするためのフックです。似たようなフックでwp_headもありますが、こちらはheadタグ内で読み込まれるものです。phpのheader関数を動作させるにはページの先頭に記述する必要があります。

以下のコードはデータベースにURLを登録する形式ではなく、ワープレのプラグイン内で直接URLを指定するものです。$urlの配列がこれに該当しますので、変更や追加は、ここで行います。

<?php
/*
Plugin Name: AAA
*/
add_action('get_header', function(){
$url=['https://example.com/1/' => 'https://example.com/2/'];
if(!empty(get_the_permalink()) && array_key_exists(get_the_permalink(),$url)){
foreach($url as $key => $val){
if(get_the_permalink()==$key){
header("Location: ".$val, true, 301);
exit;
}
}
}
});
?>

尚、プラグインを有効化する際に「プラグインの有効化中に1文字の予期しない出力が生成されました。 “headers already sent” メッセージや RSS フィードの問題、その他の不具合に気づいた場合、このプラグインの停止または削除を試してください。」などと出力されることがあります。この場合、プラグインファイルの一番上に改行や空白、その他の文字列が入っている可能性があります。解消するには該当部分を取り除いて下さい。

まとめ

基本的にワープレを使っていれば、Plugin化したほうが管理が楽かも知れません。上記の方法ではディレクトリ単位でファイル丸ごとの転送はできませんが、get_the_category関数を使えば可能です。htaccessは昔ながらの設定方法ですが、一般にはダウンロードして書き換えてアップロードするという工程が入りますので、煩わしさを感じます。技術的にhtaccessをワープレの管理画面上から書き換えることも可能ですが、ワープレを使っているのであればhtaccessを書き換えるより、条件分岐で処理したほうが良いような気がします。