2026年7月12日
2026年7月12日
WordPressの.htaccessエラー(500エラー・パーマリンクが機能しない)を解決する方法
はじめに
WordPressの.htaccessファイルを編集したら500 Internal Server Errorになった・カスタムパーマリンクに変更したのに投稿のURLにアクセスすると404になる・WordPress管理画面の「パーマリンク設定」で「変更を保存」してもパーマリンクが機能しない・共有ホスティングで.htaccessが書き込み権限なく自動更新されないといった問題は、シンタックスエラー・mod_rewriteの無効化・AllowOverride None設定・ファイルパーミッションの不正が原因です。
症状・原因
.htaccessに構文エラーがありApacheが設定を読み込めない(500エラーの原因)- サーバーの
設定でAllowOverride Noneが設定されており.htaccessが無視されている mod_rewriteモジュールがApacheで有効化されていないwp-content/ディレクトリの所有者がWebサーバーのユーザーと異なりファイルを書き込めない
解決手順
ステップ1:.htaccessの状態を診断する
# .htaccessの構文をApacheでテスト(root権限が必要)
# apachectl -t
# .htaccessファイルの存在と権限を確認
ls -la /var/www/html/.htaccess
# mod_rewriteが有効か確認
wp eval "
// Apache mod_rewrite の確認
if (function_exists('apache_get_modules')) {
\$modules = apache_get_modules();
echo 'mod_rewrite: ' . (in_array('mod_rewrite', \$modules) ? 'enabled' : 'DISABLED') . PHP_EOL;
} else {
echo 'apache_get_modules() not available (Nginx or PHP-FPM?)' . PHP_EOL;
}
"
# .htaccessの内容を確認
wp eval "
\$htaccess = ABSPATH . '.htaccess';
if (file_exists(\$htaccess)) {
echo file_get_contents(\$htaccess);
} else {
echo '.htaccess does not exist!' . PHP_EOL;
}
"
# パーマリンク設定を確認
wp option get permalink_structure
wp rewrite list --format=table | head -20
ステップ2:.htaccessを正しいWordPress標準に戻す
# .htaccessを標準形式に戻す(WP-CLIで再生成)
wp eval "
global \$wp_rewrite;
\$wp_rewrite->set_permalink_structure('/%postname%/');
\$wp_rewrite->flush_rules(true);
echo 'Permalink structure reset and .htaccess regenerated.' . PHP_EOL;
"
# .htaccessの書き込み権限を修正
# chmod 644 /var/www/html/.htaccess
# chown www-data:www-data /var/www/html/.htaccess
WordPress標準の.htaccessの正しい内容:
# BEGIN WordPress
# このブロックは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
ステップ3:Apache・Nginxの設定でmod_rewriteを有効化する
Apacheの場合(/etc/apache2/sites-available/000-default.conf):
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/html
<Directory /var/www/html>
Options Indexes FollowSymLinks
AllowOverride All # .htaccess を有効化(None → All)
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
# mod_rewriteを有効化してApacheを再起動(Ubuntuの場合)
# a2enmod rewrite
# systemctl restart apache2
# Apache設定テスト
# apachectl configtest
# Nginx + PHP-FPM の場合(try_files で WordPress をサポート)
# server {
# location / {
# try_files $uri $uri/ /index.php?$args;
# }
# }
ステップ4:.htaccessにカスタムルールを安全に追加する
// functions.php: .htaccessにカスタムルールをWordPressのAPIで追加
// WordPress のフックを使って .htaccess に安全にルールを追加
add_filter('mod_rewrite_rules', function(string $rules): string {
$custom = "<IfModule mod_headers.c>\n";
$custom .= " Header always set X-Content-Type-Options nosniff\n";
$custom .= " Header always set X-Frame-Options SAMEORIGIN\n";
$custom .= "</IfModule>\n\n";
return $custom . $rules;
});
// PHP経由で .htaccess に書き込む(insert_with_markers を使用)
add_action('admin_init', function(): void {
if (!isset($_GET['add_htaccess_rules']) || !current_user_can('manage_options')) {
return;
}
$htaccess_path = ABSPATH . '.htaccess';
$lines = [
'Options -Indexes',
'ServerSignature Off',
];
insert_with_markers($htaccess_path, 'Security Rules', $lines);
wp_die('.htaccess security rules added.');
});
# .htaccess: セキュリティ強化ルール(# BEGIN WordPress の前に追加)
# PHPファイルへの直接アクセスを制限
<Files "wp-config.php">
Require all denied
</Files>
# xmlrpc.phpを無効化(使用しない場合)
<Files "xmlrpc.php">
Require all denied
</Files>
# .htaccessファイル自体を保護
<Files ".htaccess">
Require all denied
</Files>
ステップ5:パーマリンクとリライトルールを最適化する
// functions.php: カスタムリライトルールの追加
// カスタムリライトルールを追加
add_action('init', function(): void {
// /api/{endpoint} を /index.php?api_endpoint={endpoint} にマップ
add_rewrite_rule(
'^api/([^/]+)/?$',
'index.php?api_endpoint=$matches[1]',
'top' // 優先度: 'top' または 'bottom'
);
});
// カスタムクエリ変数を登録
add_filter('query_vars', function(array $vars): array {
$vars[] = 'api_endpoint';
return $vars;
});
// リライトルールが更新されているか確認してフラッシュ
add_action('init', function(): void {
if (get_option('my_plugin_version') !== '1.0.0') {
flush_rewrite_rules();
update_option('my_plugin_version', '1.0.0');
}
});
# 現在のリライトルールを確認
wp rewrite list --format=table
# リライトルールをリセット
wp rewrite flush --hard
# 特定のURLが正しくマッチするか確認
wp eval "
\$url = '/product/sample-item/';
\$request = new WP(\$url);
\$request->parse_request();
echo 'Matched: ' . print_r(\$request->query_vars, true);
"
注意事項
.htaccessの# BEGIN WordPress〜# END WordPressの間のコードは編集しないでください。この範囲はWordPressが自動管理しており、パーマリンク設定保存時に上書きされますAllowOverride Allはセキュリティ上のリスクがあります。本番環境では必要なディレクティブのみを許可するAllowOverride FileInfo Optionsなどの絞り込みを検討してください- Nginxを使用している場合は
.htaccessは機能しません。Nginxの設定ファイルに直接try_files $uri $uri/ /index.php?$args;を記述する必要があります
まとめ
WordPress .htaccessエラーの解決は①apachectl -tで構文チェック・ls -laで権限確認・apache_get_modules()でmod_rewrite有効確認・wp option get permalink_structureで設定確認、②$wp_rewrite->flush_rules(true)でWordPressの標準.htaccessを再生成・chmod 644とchownで権限を正しく設定、③ApacheのにAllowOverride Allを設定・a2enmod rewriteでmod_rewriteを有効化・Nginxはtry_filesでWordPressをサポート、④mod_rewrite_rulesフィルターまたはinsert_with_markers()でカスタムルールを追加・wp-config.phpやxmlrpc.phpへの直接アクセスをブロック、⑤add_rewrite_rule()でカスタムリライトを追加・query_varsフィルターでカスタムクエリ変数を登録・バージョン比較でflush_rewrite_rules()を一度だけ実行の手順で解決します。