WordPress のファイルをサイトのいちばん上 (ドキュメントルート) に置くと、ほかのファイルと混ざって見通しが悪くなります。WordPress には、本体を /blog/ のようなサブディレクトリに置いたまま、サイトのトップ (https://example.com/) で表示する方法が用意されています。ここでは、その手順と、裏で働いている Apache の mod_rewrite (URL を書き換えるモジュール) の基本を説明します。

2 つのアドレスの設定

管理画面の「設定」→「一般」には、2 つのアドレスがあります。

  • WordPress アドレス (URL): WordPress の本体のファイルがある場所。管理画面もこの下になる (例: https://example.com/blog)
  • サイトアドレス (URL): 訪問者がサイトを開くときのアドレス (例: https://example.com)

ふつうは同じ値ですが、本体をサブディレクトリに置いてトップで表示するときは、2 つを別の値にします。

公式の手順

WordPress の公式の資料に沿うと、本体を /blog/ に置いている場合の手順は次のとおりです。

  1. 作業の前に、データベースとファイルをバックアップする (WordPress のバックアップ を参照)
  2. 「設定」→「一般」で、WordPress アドレスを https://example.com/blog、サイトアドレスを https://example.com にして保存する。この時点で表示がおかしくなっても、続けて進める
  3. /blog/ にある index.php と .htaccess を、ドキュメントルートへコピーする (移動ではなくコピー)
  4. ドキュメントルートにコピーした index.php の、wp-blog-header.php を読み込む行を、/blog/ の下を指すように書き換える
  5. https://example.com/blog/wp-admin/ からログインし、「設定」→「パーマリンク」を開いて、そのまま保存し直す (.htaccess が書き直される)
<?php
// ドキュメントルートに置いた index.php
define( 'WP_USE_THEMES', true );

// 本体のある /blog/ の wp-blog-header.php を読み込む
require __DIR__ . '/blog/wp-blog-header.php';

WordPress の版によっては、この行が require dirname( __FILE__ ) . '/wp-blog-header.php'; と書かれています。どちらの場合も、パスに /blog を足すだけです。

ドキュメントルートの .htaccess には、WordPress が次のような設定を書き込みます。

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

版によっては、Authorization ヘッダーを PHP に渡す行なども加わります。# BEGIN WordPress と # END WordPress の間は WordPress が書き換えるので、自分で足す設定は、その外に書きます。

mod_rewrite の基本

上の設定を 1 行ずつ読むと、mod_rewrite の基本がわかります。

  • RewriteEngine On: この場所で、URL の書き換えを有効にする
  • RewriteBase /: .htaccess で、書き換え先を相対パスで書いたときの基準になる URL のパス
  • RewriteRule パターン 書き換え先 [フラグ]: URL のパスがパターン (正規表現) に一致したら、書き換え先で処理する。書き換え先の - は「書き換えない」という意味
  • RewriteCond: 直後の RewriteRule 1 つにだけかかる条件。%{REQUEST_FILENAME} はリクエストに対応するサーバー上のファイルのパスで、-f は「ファイルとして存在する」、-d は「ディレクトリとして存在する」、先頭の ! は否定

つまり、この設定は「実在するファイルやディレクトリへのリクエストはそのまま返し、それ以外はすべて /index.php に処理を任せる」という意味です。画像や CSS、/blog/wp-admin/ は実在するのでそのまま表示され、投稿の URL のように実在しないパスは WordPress が処理します。

.htaccess の中では、パターンと比べるパスは、その .htaccess があるディレクトリからの相対パスになり、先頭の / が付きません。^index\.php$ が /index.php へのリクエストに一致するのはこのためです。

よく使うフラグは次のとおりです。

  • L: 書き換えをここで終える。ただし .htaccess では、書き換えたあとのリクエストに対して、規則がもう一度最初から適用される。同じ規則に何度も一致して転送や書き換えが止まらなくならないよう、条件で除外する
  • R=301: ブラウザーに恒久的な転送 (リダイレクト) を返す。アドレス欄の URL も変わる
  • QSA: 書き換え先にクエリ (? 以降) を書いたとき、元のクエリを後ろに付け足す。付けないと、元のクエリは捨てられる
RewriteEngine On
RewriteBase /

# 古い URL を新しい URL へ恒久的に転送する
RewriteRule ^old-page\.html$ /new-page.html [R=301,L]

# /items/12 を item.php?id=12 で処理する (/items/12?sort=new なら sort=new も引き継ぐ)
RewriteRule ^items/([0-9]+)$ item.php?id=$1 [QSA,L]

.htaccess で mod_rewrite を使うには、サーバーで mod_rewrite が有効になっていて、AllowOverride で .htaccess での設定が許可されている必要があります。www の有無をそろえる転送の書き方は、www 付きの URL を www 無しの URL にリダイレクトする で取り上げています。

管理画面に入れなくなったときの戻し方

アドレスの設定を打ち間違えると、デザインが崩れたり、ログインの画面へ転送され続けたりして、管理画面に入れなくなることがあります。設定はデータベースに保存されているので、管理画面が開けないと直せません。

そのようなときは、wp-config.php に 2 つの定数を書きます。場所は、「stop editing」(日本語版では「編集が必要なのはここまでです」) と書かれたコメントの行より上です。

// wp-config.php に書き足す
define( 'WP_HOME', 'https://example.com' );        // サイトアドレス
define( 'WP_SITEURL', 'https://example.com/blog' ); // WordPress アドレス

この 2 つの定数は、データベースの値より優先されます。ただし、データベースの値そのものは変わらないので、定数を消すと元の値に戻ります。データベースの値は、WP-CLI (WordPress をコマンドで操作するツール) で直せます。

wp option update home 'https://example.com'
wp option update siteurl 'https://example.com/blog'

.htaccess の書き間違いで「500 Internal Server Error」になったときは、FTP で .htaccess の名前を変えるなどして、いったん外すと元に戻ります。

まとめ

  • 本体をサブディレクトリに置いてトップで表示するには、「WordPress アドレス」と「サイトアドレス」を別の値にする
  • index.php と .htaccess をドキュメントルートへコピーし、index.php の読み込み先をサブディレクトリに書き換える
  • WordPress の .htaccess は、実在しないパスへのリクエストを index.php に任せる設定。RewriteCond の -f と -d で見分ける
  • フラグは、L (ここで終える)、R=301 (恒久的な転送)、QSA (元のクエリを引き継ぐ) をよく使う
  • 管理画面に入れなくなったら、wp-config.php で WP_HOME と WP_SITEURL を指定して戻す

参考