本文へスキップ

WordPressをサブディレクトリに設置する方法(応用編)

WordPressをサブディレクトリに設置したあと、パーマリンク(記事URLの形式)を変えることがあります。その瞬間、全ページが404になることがあります。

管理画面を開こうとして、ブラウザがリダイレクトを繰り返したまま止まることも。設置の手順そのものは正しく終わっていても、こうした不具合は出ます。

サブディレクトリ設置は、設定そのものより「設置したあと」に出てくる不具合の切り分けのほうが厄介です。

症状だけ見ても原因が分かりにくく、心当たりのない場所が壊れているように見えます。

この記事は、WordPressをサブディレクトリにインストールしてURLを隠す方法の続編です。

そちらに設置手順はまとめてあるので、ここでは実案件で踏んだトラブルと、その原因・直し方を扱います。

前提は同じです。WordPress本体は /wp に置き、公開URLは https://example.com です。

パーマリンクを変えたら全ページが404になる

いちばん多いのがこれです。

トップページは出るのに、投稿ページや固定ページを開くと404になります。「お探しのページは見つかりませんでした」やサーバーの404画面が出ます。

パーマリンクを変えたあと投稿を開いたときのNot Found画面

原因:WordPressはルートの.htaccessを書き換えられない

パーマリンクの設定を保存すると、WordPressは .htaccess を自動で書き換えます。

このとき書き換えに行くのは、WordPress本体が入っている /wp の中の .htaccess です。

ところがサブディレクトリ設置では、実際に読み込まれているのはルートに置いた .htaccess のほうです。

ルート側はWordPressの管理外なので、いくら管理画面で保存し直しても中身は古いまま。結果、URLの書き換えルールが実態と合わなくなって404になります。

「パーマリンク設定を開いて保存し直すと直る」という定番の対処法が通用しないのは、このためです。

直し方:ルートの.htaccessを手で書く

FTPソフトでルートの .htaccess をダウンロードして、WordPressのブロックを次の内容に差し替えます。

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

見るべきポイントは2箇所だけです。

  • RewriteBase / — ここが /wp/ になっていたら書き換える。基準になるパスは公開URL側です
  • RewriteRule . /index.php [L] — 飛び先はルート直下の index.php

基礎編の手順どおりに進めていれば、この2箇所は正しく揃っています。

サイトアドレスを変更したあとに /wp から .htaccess を取得する順番だったはずです。

ただしサーバーの環境や作業の順番によっては /wp/ のまま残ることがあります。404が出たら、まずここを開いて確認してください。

RewriteCond や正規表現の中身を深く理解せずに進めても構いません。上で見た2箇所さえ合っていれば、そのまま動きます。

/wp の中の .htaccess は、/wp/ 配下へ直接アクセスされたときだけ働きます。残しておいて構いません。

WordPressが書き換えるhtaccessとサーバーが読むhtaccessの違い
パーマリンク設定の画面下部。htaccessが書き込めないというエラーと、貼り付けるリライトルールが表示されている

管理画面がリダイレクトループになる

ログインしようとすると「リダイレクトが繰り返し行われました」とブラウザに止められる状態です。管理画面に入れないので、WordPress側から直せません。

原因:WordPressアドレスまで変えてしまった

設定→一般にある2つのURLのうち、変えていいのは「サイトアドレス」だけです。

「WordPressアドレス」まで https://example.com にしてしまうと危険です。

WordPressが、自分の本体はルートにあると思い込みます。実際のファイルは /wp にあります。

探しに行っては見つからず、また転送する。この往復が止まらなくなります。

もうひとつありがちなのが、ルートの index.php の書き換え漏れです。

/wp-blog-header.php の前に足すはずの /wp が抜けているケースです。この場合も、同じようにWordPress本体を見つけられません。

直し方:wp-config.phpで固定する

管理画面に入れないときは、wp-config.php に直接URLを書いて上書きします。

FTPで /wp/wp-config.php をダウンロードして、次の2行を追加してください。

define( 'WP_HOME', 'https://example.com' );
define( 'WP_SITEURL', 'https://example.com/wp' );

書く場所はrequire_once ABSPATH . 'wp-settings.php'; より上です。

この行はファイルの下のほうにあります。それより下に書いても読み込まれません。

2つの定数の意味は、管理画面の2つの入力欄とそのまま対応しています。

  • WP_HOME — サイトアドレス。ユーザーがアクセスする公開URL。/wp は付けない
  • WP_SITEURL — WordPressアドレス。本体ファイルの置き場所。/wp を付ける

この2行を書くと管理画面のURL入力欄がグレーアウトして編集できなくなります

クライアントや他の制作者が触って壊す事故を構造的に防げるので、納品前提の案件では最初から書いておくのが安全だと思います。

テーマの中のパスに/wp/が混ざる

「画像だけ表示されない」「CSSが当たっていない」という症状のときがあります。

DevTools(ブラウザの開発者ツール)のNetworkタブを見ると、原因が分かります。読み込んでいるURLに /wp/ ありとなしが混在しているのです。

サブディレクトリ設置ではよく出る症状です。

home_url()とsite_url()の使い分け

WordPressにはURLを取得する関数が2種類あり、サブディレクトリ設置ではこの2つが違う値を返します。

ルート設置では同じ値になるので、普段は違いを意識せずに済んでしまうのが落とし穴です。

  • home_url()https://example.com(公開URL。ユーザーが見るサイトの入口)
  • site_url()https://example.com/wp(WordPress本体ファイルの場所)

判断の基準はシンプルで、「ユーザーに見せるリンクか、WordPressの仕組みが使うURLか」です。

  • ロゴのリンク先、トップへ戻るリンク、記事一覧へのリンク → home_url()
  • 管理画面へのリンク → admin_url()(内部で site_url() を使ってくれます)
  • ログイン・ログアウトのリンク → wp_login_url() / wp_logout_url()

ロゴまわりを書くと、こうなります。

<a href="<?php echo esc_url( home_url( '/' ) ); ?>">
  <img src="<?php echo esc_url( get_template_directory_uri() . '/img/logo.svg' ); ?>" alt="サイト名">
</a>

画像・CSS・JSは専用の関数で出す

テーマの中のファイルを読み込むときは、home_url()site_url() も使いません。専用の関数があります。

  • get_template_directory_uri() — 親テーマのURL
  • get_stylesheet_directory_uri() — 子テーマのURL(子テーマを使わないなら親と同じ)
add_action( 'wp_enqueue_scripts', function () {
    $uri  = get_template_directory_uri();
    $path = get_template_directory();

    wp_enqueue_style(
        'main',
        $uri . '/css/style.css',
        array(),
        filemtime( $path . '/css/style.css' )
    );
} );

$uri はブラウザから見たURL、$path はサーバー内部のファイルパスです。用途が違うので混ぜないようにします。

第4引数の filemtime() はファイルの更新日時です。これをバージョン番号に使うと、CSSを更新したときのキャッシュ切り替えが自動で行われます。

やってはいけないのが、site_url() にテーマのパスを手で継ぎ足すことです。

動いてしまうので気づきにくいのですが、テーマ名を変えた瞬間、サーバーを移した瞬間に壊れます。

/wp/が付いていても正常なもの

ここで混乱しやすいのですが、すべてのURLから /wp を消す必要はありません。次のものは /wp/ が付いているのが正しい状態です。

  • テーマのCSS・JS・画像(/wp/wp-content/themes/...
  • メディアライブラリにアップロードした画像(/wp/wp-content/uploads/...
  • 管理画面のURL(/wp/wp-admin/

ユーザーがアドレスバーで見るのは記事や固定ページのURLだけです。内部で読み込まれるファイルのパスは、/wp/ のままで問題ありません。

これを無理に消そうと WP_CONTENT_URL を書き換えると、プラグインが画像を見失うなど別の不具合が出ます。僕はここには触れずにおいています。

既存の静的ページと同居させるとき

「トップページと会社概要は既存のHTMLのまま、ブログだけWordPress」という構成を頼まれることがあります。

サブディレクトリ設置はこの形と相性がいいのですが、2点だけ注意が要ります。

index.htmlとindex.phpが両方あるとき

ルートに index.htmlindex.php が両方あると、多くのサーバーは前者を優先します。

WordPressをトップにしたいのに古いHTMLが出続けるときは、これを疑ってみます。

使わないHTMLは削除するのがいちばん確実です。残す事情があるなら、ルートの .htaccess に優先順を書きます。

DirectoryIndex index.php index.html

静的ディレクトリは自動で除外される

/company/ のような静的ページのフォルダは、特別な設定をしなくてもそのまま表示されます。先ほどの .htaccess にある2行が働いているからです。

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

「実際にファイルがあるとき(-f)」「実際にフォルダがあるとき(-d)」はWordPressに渡さない、という条件です。

実体があるものはそのまま返るので、静的ページは触らずに共存できます。

ただし、WordPress側に同じスラッグ(ページURLの末尾に入る文字列)の固定ページを作らないよう注意します。

/company/ というフォルダがある状態で company という固定ページを作ると、妙なことが起きます。

管理画面上は存在するのに、開くと静的HTMLが表示される、という説明のつかない状態になります。

SSL・wwwのリダイレクトが二重になる

表示は正常なのに、なんとなく表示が遅い。この場合、リダイレクトが何回も走っている可能性があります。

ありがちなのは、サーバー管理画面の「常時SSL化」設定です。これと .htaccess のhttpsリダイレクトが、両方とも有効になっているケースです。

ここにwww有無の統一が加わると、1回のアクセスで3回転送されることもあります。

確認は curl(サーバーからの応答をそのまま取得できるコマンド。macOSにもWindowsにも標準で入っています)1本でできます。

curl -sIL http://example.com/blog/ | grep -i -E "^(HTTP|location)"

-I はヘッダーだけ取得、-L はリダイレクトを最後まで追う、というオプションです。

出力に HTTP/1.1 301location: が何組並ぶかを見ます。

301が1回だけで最終URLに着いていれば正常で、2回3回と続くなら整理が必要です。

リダイレクトは1箇所にまとめるのが原則です。サーバーの機能を使うなら .htaccess には書かない。

.htaccess で管理するならサーバー側の常時SSL化はオフにする。僕はサーバー側の機能に寄せています。両方入れると転送が重なります。

公開前に見るチェック項目

サブディレクトリ設置の案件を公開する前に、僕が毎回確認しているのは次の項目です。トップページだけ見て安心すると、公開後にクライアントから連絡が来ます。

  • 投稿・固定ページ・カテゴリー・タグの各アーカイブ、ページネーション、検索結果が開くか(404はここで出ます)
  • 存在しないURLを開いたとき、サーバーの404ではなくテーマの404ページが出るか
  • https://example.com/wp/wp-admin/ でログインできるか
  • DevToolsのConsoleとNetworkに、読み込み失敗(404)の赤い行が出ていないか
  • お問い合わせフォームが送信でき、サンクスページに遷移するか
  • https://example.com/robots.txtsitemap.xml が公開URL側で開くか
  • Search Consoleに登録するプロパティが、/wp なしの公開URLになっているか

特に下2つは忘れられがちです。サイトマップのURLに /wp が混ざったままだと、検索エンジンに間違ったURLを伝えることになります。

おわりに

サブディレクトリ設置でつまずくポイントは、原因が分かってしまえばどれも単純です。

  • 404になる → ルートの .htaccess は自動更新されないので手で直す
  • リダイレクトループ → wp-config.phpWP_HOMEWP_SITEURL を書いて固定する
  • パスがおかしい → home_url()site_url() を使い分ける。テーマのファイルは get_template_directory_uri()
  • 静的ページと同居 → 実体があるファイル・フォルダは自動で除外されるので、スラッグだけ重複させない
  • 表示が遅い → curl -sIL でリダイレクト回数を数える

公開URLと本体の置き場所が食い違ったままだと、サーバー移行のたびに同じ404やループを踏みます。

僕は今も、案件のたびに .htaccessRewriteBase をまず開いて確認しています。

ここに挙げた症状で、サブディレクトリ設置のトラブルが全部片づくわけではないと思います。

ただ、公開URLと本体の場所を切り分けて考えれば、初めて見る症状でも当たりはつけられるはずです。ぜひ次の案件で試してみてください!

この記事で扱ったような設置・移行・不具合の切り分けは、AoiWebで制作と保守として承っています。

今の構成がどうなっているか分からない段階でも、お問い合わせからご相談いただけます。

Contact

お気軽にご相談ください

X(Twitter)のDM、もしくは本サイトのCONTACTページからご連絡ください。
24時間以内に返信しますので、些細なことでもお気軽にご相談ください。