東京都府中市、渋谷区のWEB制作会社Maromaroのブログです

2023.06.12

松橋一誠

「WordPress アドレス」と「サイトアドレス」を別ドメインにする時の方法

こんにちは、Maromaroの松橋です。
先日AWS環境のWordPressサイトのリニューアルを行ったのですが、「WordPress アドレス」と「サイトアドレス」を別ドメインにする方法という珍しい方法でリニューアルいたしました。
方法については、検索してもあまり良い記事が見つからなかったので、今回記事としてまとめていきたいと思います!

まずどういうことか?

AWSのEC2インスタンスを2台構成で使用し、WordPressサイトを運用しています。2台のインスタンス間の同期は、プライマリのインスタンスから数分程度で実行されています。

ALBのロードバランシングにより、公開ドメインから2台のインスタンスへのルーティングが行われています。プライマリインスタンスは特定のIPアドレスのみを許可し、公開ドメインとは別の専用ドメインで接続が可能な状態でした。

しかし、セカンダリのインスタンスにファイルを配置すると、数分後にプライマリからの同期機能によりファイルが削除されてしまいます。これは、プライマリからのファイルの完全同期が行われる仕様のためです。そのため、画像などのファイルアップロードはプライマリインスタンスで行う必要がありました。

そのため、ログイン・管理画面が表示されている時は、プライマリインスタンスへの専用ドメインでアクセスできるように設定し、一方では、TOPページや固定ページなどのログイン・管理画面以外のフロントのページが表示されている時は、公開ドメインでALB接続にて表示させることにいたしました。

コード

まず、ホスト情報を含む配列を返す関数を作成します。
ドメイン単位で表示の切替を行いつつも、テスト環境と本番環境で同じコードを利用したいので、この配列には、テスト環境と本番環境のそれぞれのホスト名 公開ドメイン(※以降 alb_urlと呼称)とプライマリインスタンスへの専用ドメイン(※以降、primary_urlと呼称)が含まれています。


/**
 * ホスト配列を返す
 * 
 * @return array ホスト情報を含む配列
 */
function get_this_host_array() {
  return array(
    'test' => array(
      'alb_url' => 'test.www.example.com',
      'primary_url' => 'primary.test.example.com',
    ),
    'prod' => array(
      'alb_url' => 'www.example.com',
      'primary_url' => 'primary.example.com',
    )
  );
}

次に、現在のホスト($_SERVER[‘HTTP_HOST’])がテスト環境のものか、本番環境のものかを判断し、そのキー(’test’または’prod’)を返す関数を作成します。



/**
 * 現在のホストのキーを取得
 * 
 * @return string|null ホストキー。該当するものがなければnull
 */
function get_this_host_key() {
  $this_hosts = get_this_host_array();

  foreach($this_hosts as $host_key => $this_host){
    if(
      $this_host['alb_url'] === $_SERVER['HTTP_HOST'] ||
      $this_host['primary_url'] === $_SERVER['HTTP_HOST']
    ){
      return $host_key;
    }
  }

  return null; // ホストキーが見つからない場合はnullを返す
}


現在のホストに対応する ‘alb_url’ と ‘primary_url’ をそれぞれ返す関数を作成します。
さらに何回も関数で取得すると表示速度に影響が出るかと思いますので、グローバル変数の宣言をしておくと便利です。



/**
 * alb_url 取得
 * 
 * @return string|null alb_url。該当するものがなければnull
 */
function get_alb_url() {
  $this_host_key = get_this_host_key();
  $this_host_array = get_this_host_array();

  return $this_host_array[$this_host_key]['alb_url'] ?? null; // ホストキーが見つからない場合はnullを返す
}

$alb_url = get_alb_url();
global $alb_url;



/**
 * primary_url 取得
 * 
 * @return string|null primary_url。該当するものがなければnull
 */
function get_primary_url() {
  $this_host_key = get_this_host_key();
  $this_host_array = get_this_host_array();

  return $this_host_array[$this_host_key]['primary_url'] ?? null; // ホストキーが見つからない場合はnullを返す
}

$primary_url = get_primary_url();
global $primary_url;


header.phpにalb_urlへのリダイレクト用のアクションを追加します。

do_action('redirect_alb_url');

現在のホストが ‘primary_url’ または ‘alb_url’ に一致する場合、それぞれ ‘alb_url’ または ‘primary_url’ にリダイレクトさせる処理を記述します。
※ただし、if文に!is_preview()の条件を追加し、プレビューモードではリダイレクトは行われないようにします。



/**
 * 「primary_url」→「alb_url」リダイレクト
 */
add_filter( 'redirect_alb_url', function() {
  global $primary_url, $alb_url;

  if($_SERVER['HTTP_HOST'] === $primary_url && !is_preview() ){
    $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http';
    if(wp_redirect($protocol.'://'.$alb_url.$_SERVER['REQUEST_URI'])){
      exit;
    }
  }
});



add_action( 'admin_init', 'redirect_primary_url');
add_action( 'login_init', 'redirect_primary_url' );

/**
 * 「alb_url」→「primary_url」リダイレクト
 */
function redirect_primary_url() {
  global $alb_url, $primary_url;

  if($_SERVER['HTTP_HOST'] === $alb_url && !is_preview()){
    $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http';
    if(wp_redirect($protocol.'://'.$primary_url.$_SERVER['REQUEST_URI'])){
      exit;
    }
  }
}

次に、wp_head、wp_footer、the_content内の ‘primary_url’ を ‘alb_url’ に置換します。
※管理画面 or プレビューモードである場合は置換は行われません。



/**
 * 「primary_url」→「alb_url」に置換
 */
add_action( 'wp_head', 'replace_filter_start', 0 );
add_action( 'wp_head', 'replace_filter_end', 100 );
add_action( 'wp_footer', 'replace_filter_start', 0 );
add_action( 'wp_footer', 'replace_filter_end', 100 );
add_filter('the_content', 'get_replace_filter_info', 12);

/**
 * コンテンツ内の「primary_url」を「alb_url」に置換
 * 
 * @param string $content コンテンツ
 * @return string 置換後のコンテンツ
 */
function get_replace_filter_info($content) {
  global $alb_url, $primary_url;

  if(!is_admin() && $_SERVER['HTTP_HOST'] === $alb_url && !is_preview()){
    return str_replace($primary_url, $alb_url, $content);
  }

  return $content;
}

/**
 * コンテンツ内の「primary_url」を「alb_url」に置換するコールバック関数を返す
 * 
 * @param string $content コンテンツ
 * @return string 置換後のコンテンツ
 */
function return_replace_filter($content) {
  return get_replace_filter_info($content);
}



/**
 * 出力バッファリングを開始し、コンテンツ内の「primary_url」を「alb_url」に置換するコールバック関数を設定
 */
function replace_filter_start() {
  ob_start( 'return_replace_filter' );
}

/**
 * 出力バッファリングを終了し、バッファの内容を送信
 */
function replace_filter_end() {
  ob_end_flush();
}

さいごにwp-config.phpにアクセスされたドメインによって「WordPress アドレス」と「サイトアドレス」を可変・動的にします。



if($_SERVER['HTTP_HOST'] === 'primary.example.com'){

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

if($_SERVER['HTTP_HOST'] === 'www.example.com'){

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

さいごに

色々関数を作成しましたが、行った対処としてはリダイレクトと置換になります。これでなんとか「WordPress アドレス」と「サイトアドレス」を別ドメインにしてサイトを公開させることができました。
色々関数を作成しましたが、行った対処としてはリダイレクトと置換になります。

AWSを利用されている環境ですとこのような構成あるのだなと勉強になりました!

以上、Maromaroの松橋でした。