2026年6月27日

2026年6月27日

Redirectionプラグインのエラーを解決する方法

はじめに

Redirectionでリダイレクトを設定しても302や301が正しく返らない・アクセスログが記録されない・.htaccessへの書き込みができない・設定したリダイレクトが無限ループを起こすといった問題は、REST APIの疎通・パーミッション・リダイレクト条件の設定ミスが原因です。

症状・原因

  • リダイレクトを追加しても元のURLにアクセスすると404になる
  • 「REST APIの接続テスト失敗」というエラーが管理画面に表示される
  • .htaccessを選択しても「ファイルへの書き込み権限がありません」とエラーになる
  • リダイレクト設定後にサイトが無限ループで表示できなくなった

解決手順

ステップ1:Redirectionの状態を確認する

# Redirectionのバージョンとリダイレクト一覧を確認
wp eval "
if (class_exists('Red_Plugin')) {
    echo 'Redirection version: ' . REDIRECTION_VERSION . PHP_EOL;
}

// リダイレクト一覧を確認
\$items = Red_Item::get_all();
echo 'Total redirects: ' . count(\$items) . PHP_EOL;
foreach (array_slice(\$items, 0, 5) as \$item) {
    printf('  [%s] %s → %s (hits: %d)' . PHP_EOL,
        \$item->is_enabled() ? 'ON' : 'OFF',
        \$item->get_url(),
        \$item->get_action_data(),
        \$item->get_hits()
    );
}
"

# REST APIの疎通確認
wp eval "
\$response = wp_remote_get(rest_url('redirection/v1/redirect'), [
    'headers' => ['X-WP-Nonce' => wp_create_nonce('wp_rest')],
]);
if (is_wp_error(\$response)) {
    echo 'REST API error: ' . \$response->get_error_message() . PHP_EOL;
} else {
    echo 'REST API status: ' . wp_remote_retrieve_response_code(\$response) . PHP_EOL;
}
"

ステップ2:リダイレクトをプログラムで管理する

// functions.php: Redirectionのプログラム管理

// ① リダイレクトをコードで追加
function add_redirect(string $source, string $target, int $code = 301): bool {
    if (!class_exists('Red_Item')) return false;

    $data = [
        'url'         => $source,
        'action_type' => 'url',
        'action_data' => ['url' => $target],
        'match_type'  => 'url',
        'status'      => 'enabled',
        'group_id'    => 1,
        'action_code' => $code,
    ];

    $item = Red_Item::create($data);
    return !is_wp_error($item);
}

// ② 投稿スラッグ変更時に自動でリダイレクトを追加
add_action('post_updated', function(int $post_id, \WP_Post $post_after, \WP_Post $post_before): void {
    if ($post_before->post_name === $post_after->post_name) return;
    if ($post_after->post_status !== 'publish') return;

    $old_url = get_permalink($post_before);
    $new_url = get_permalink($post_after);

    if ($old_url && $new_url && $old_url !== $new_url) {
        add_redirect(
            wp_make_link_relative($old_url),
            wp_make_link_relative($new_url),
            301
        );
        error_log(sprintf('[Redirection] Auto-redirect: %s → %s', $old_url, $new_url));
    }
}, 10, 3);

// ③ 条件付きリダイレクト(モバイル端末の場合)
add_action('template_redirect', function(): void {
    if (!is_singular('product')) return;

    $user_agent = $_SERVER['HTTP_USER_AGENT'] ?? '';
    $is_mobile  = preg_match('/Mobile|Android|iPhone/i', $user_agent);

    if ($is_mobile) {
        $mobile_url = add_query_arg('view', 'mobile', get_permalink());
        // wp_redirect($mobile_url, 302); // 必要に応じてコメント解除
    }
});

ステップ3:REST APIと.htaccessの問題を解決する

// functions.php: REST API・.htaccess設定の修正

// ① REST APIへのアクセスを許可
add_filter('rest_authentication_errors', function($result) {
    // Redirectionが使用するREST APIを認証エラーから除外
    if (!empty($result)) {
        $route = $GLOBALS['wp']->query_vars['rest_route'] ?? '';
        if (str_starts_with($route, '/redirection/')) {
            return null; // 認証エラーを無視
        }
    }
    return $result;
});

// ② セキュリティプラグインによるREST API制限を解除
add_filter('rest_namespace_index', function(array $data): array {
    // REST APIが正常に応答していることを確認するためのデバッグ用
    $data['redirection_check'] = true;
    return $data;
});
# .htaccessのパーミッションを確認・修正
ls -la /var/www/html/.htaccess

# .htaccessに書き込み権限を付与
chmod 644 /var/www/html/.htaccess

# Redirectionが生成するhtaccessルールを確認
wp eval "
\$groups = Red_Group::get_all();
foreach (\$groups as \$group) {
    if (\$group->get_module_id() === 2) { // Apache module
        echo 'Apache group: ' . \$group->get_name() . PHP_EOL;
        \$items = Red_Item::get_for_group(\$group->get_id());
        echo 'Redirects in group: ' . count(\$items) . PHP_EOL;
    }
}
"

ステップ4:リダイレクトループを診断・修正する

// functions.php: リダイレクトループ防止

// ① リダイレクト前に循環チェック
add_filter('redirection_redirect_url', function(string $url, \Red_Item $item): string {
    $source = $item->get_url();

    // ソースとターゲットが同じ場合はリダイレクトをスキップ
    if (parse_url($url, PHP_URL_PATH) === parse_url($source, PHP_URL_PATH)) {
        error_log(sprintf('[Redirection] Loop detected: %s → %s', $source, $url));
        return ''; // 空文字を返してリダイレクトをキャンセル
    }

    return $url;
}, 10, 2);

// ② 無限ループ発生時の緊急解除用コード
// wp-config.phpまたはfunctions.phpに一時的に追加して使用
// define('REDIRECTION_DISABLE', true);
# ループしているリダイレクトを特定・削除
wp eval "
\$items = Red_Item::get_all();
foreach (\$items as \$item) {
    \$source = \$item->get_url();
    \$target = \$item->get_action_data();

    // ソース = ターゲット の場合
    if (\$source === \$target || rtrim(\$source, '/') === rtrim(\$target, '/')) {
        printf('Loop redirect found: ID=%d %s → %s' . PHP_EOL,
            \$item->get_id(), \$source, \$target);
        // \$item->delete(); // コメント解除で削除
    }
}
"

ステップ5:リダイレクトのインポートとパフォーマンス

// functions.php: Redirectionのパフォーマンス最適化

// ① リダイレクトログを最適化
add_filter('redirection_log_days', function(int $days): int {
    return 30; // ログ保持期間を30日に設定
});

// ② 高トラフィックページのリダイレクト確認をキャッシュ
add_filter('redirection_can_redirect', function(bool $can, string $url): bool {
    $cache_key = 'redir_check_' . md5($url);
    $cached    = wp_cache_get($cache_key, 'redirection');

    if ($cached !== false) {
        return (bool)$cached;
    }

    wp_cache_set($cache_key, $can, 'redirection', 300); // 5分キャッシュ
    return $can;
}, 10, 2);
# CSVからリダイレクトを一括インポート
wp eval "
// CSVフォーマット: old_url,new_url,status_code
\$csv_data = file_get_contents('/tmp/redirects.csv');
\$lines = explode(PHP_EOL, trim(\$csv_data));
\$count = 0;
foreach (\$lines as \$line) {
    \$parts = str_getcsv(\$line);
    if (count(\$parts) < 2) continue;

    [\$source, \$target, \$code] = array_pad(\$parts, 3, '301');
    \$data = [
        'url'         => trim(\$source),
        'action_type' => 'url',
        'action_data' => ['url' => trim(\$target)],
        'match_type'  => 'url',
        'status'      => 'enabled',
        'group_id'    => 1,
        'action_code' => (int)\$code,
    ];
    \$item = Red_Item::create(\$data);
    if (!\$item->is_error()) \$count++;
}
echo 'Imported: ' . \$count . ' redirects' . PHP_EOL;
"

注意事項

  • Redirectionは初期設定でWordPressのリダイレクト処理(PHPモジュール)を使用します。.htaccessモジュールを選択すると処理が速くなりますが、AllowOverride AllがApacheで有効になっている必要があります
  • リダイレクト設定後に無限ループが発生した場合はwp-config.phpdefine('REDIRECTION_DISABLE', true);を一時的に追加してプラグインを無効化できます
  • REST APIエラーが表示される場合、WordfenceなどのセキュリティプラグインがREST APIへのアクセスをブロックしている可能性があります。「Wordfence → ファイアウォール → ブロック一覧」で/wp-json/へのアクセスが許可されているか確認してください

まとめ

Redirection修復は①Red_Item::get_all()でリダイレクト一覧確認・REST API疎通テスト、②Red_Item::create()でプログラムによるリダイレクト追加・post_updatedフックでスラッグ変更時の自動リダイレクト、③rest_authentication_errorsフィルターでREST API認証エラーを解除・.htaccessパーミッション修正、④redirection_redirect_urlフィルターで循環リダイレクトを検知・REDIRECTION_DISABLE定数で緊急無効化、⑤redirection_log_daysフィルターでログ保持期間を設定しwp_cache_set()でリダイレクト確認をキャッシュする手順で解決します。

お気軽にご相談ください

お見積りへ お問い合わせへ