べんりワザ・WordPressのマルチサイト

マルチサイトで今どの子サイトかをslugで判別する

マルチサイトで「今どのサイトを表示しているか」を判別して出し分ける方法。スラッグ(パス)での判定を軸に、IDやドメインでの判定、URLからサイトIDを引く関数まで整理しました。

マルチサイトで「このサイトだけ表示を変えたい」ときは、スラッグ(URLのパス)で判別するのが基本です。IDは環境によってズレることがあるため、URLに現れるスラッグのほうが安全です。

<?php
$slug = trim(get_blog_details()->path, '/');   // 例: 'shop'(メインサイトは空文字)

if ($slug === 'shop') {
  // ショップサイトだけの処理
}
?>

判別に使える情報

<?php
get_current_blog_id();                       // 3(サイトID)
trim(get_blog_details()->path, '/');         // 'shop'(サブディレクトリ型のスラッグ)
get_blog_details()->domain;                  // 'example.com'(サブドメイン型ならshop.example.com)
get_bloginfo('name');                        // サイト名
is_main_site();                              // メインサイトならtrue
get_main_site_id();                          // メインサイトのID
home_url();                                  // そのサイトのトップURL
?>
判定に使うもの安定性使いどころ
スラッグ(path)◎ URLと一致基本これ。サブディレクトリ型
ドメイン◎ URLと一致サブドメイン型・独自ドメイン運用
サイトID△ 環境でズレる同一環境内の一時的な処理
is_main_site()親サイトかどうかの分岐

ヘルパー関数にしておく

判定を何か所にも書くと修正が大変になります。関数1つにまとめるのがおすすめです。

<?php
/** 現在のサイトのスラッグ(メインサイトは 'main') */
function mynet_site_slug() {
  if (!is_multisite()) {
    return 'main';
  }
  if (is_main_site()) {
    return 'main';
  }

  $details = get_blog_details();

  // サブドメイン型(shop.example.com → shop)
  if (defined('SUBDOMAIN_INSTALL') && SUBDOMAIN_INSTALL) {
    return explode('.', $details->domain)[0];
  }

  // サブディレクトリ型(/shop/ → shop)
  return trim($details->path, '/');
}

サブドメイン型・サブディレクトリ型のどちらでも同じ呼び出し方になるので、あとから型を変えても影響が1か所で済みます。

<?php if (mynet_site_slug() === 'shop') : ?>
  <p class="notice">送料は全国一律500円です。</p>
<?php endif; ?>

サイトごとの設定を配列で持つ

分岐が増えてきたら、ifを並べるより設定を1つの配列に集めるほうが読みやすくなります。

<?php
function mynet_config($key = null) {
  $all = [
    'main'   => ['color' => '#333333', 'label' => '本部', 'tel' => '03-1111-1111'],
    'shop'   => ['color' => '#e8618c', 'label' => 'ショップ', 'tel' => '03-2222-2222'],
    'school' => ['color' => '#3d7ea6', 'label' => 'スクール', 'tel' => '03-3333-3333'],
  ];

  $config = $all[mynet_site_slug()] ?? $all['main'];

  return $key === null ? $config : ($config[$key] ?? null);
}
?>

<p>お問い合わせ:<?php echo esc_html(mynet_config('tel')); ?></p>

サイトを増やすときは配列に1行足すだけ。分岐を探して回る必要がなくなります。

べんりワザマルチサイトで親子テーマを設計するテーマ側の設計(親子テーマ/1テーマで分岐)はこちら

bodyのclassに入れてCSSで分ける

PHPで分岐せずに済むものは、CSS側に寄せると保守が楽です。

<?php
add_filter('body_class', function ($classes) {
  $classes[] = 'site-' . sanitize_html_class(mynet_site_slug());
  return $classes;
});
.site-shop { --color-primary: #e8618c; }
.site-school { --color-primary: #3d7ea6; }
.site-shop .site-header::after { content: "SHOP"; }

URLからサイトIDを調べる

「あのサイトの投稿を取りたいが、IDが分からない」ときに使います。

<?php
$blog_id = get_blog_id_from_url('example.com', '/shop/');   // サブディレクトリ型
$blog_id = get_blog_id_from_url('shop.example.com', '/');   // サブドメイン型

// 見つからない場合は0が返る
if ($blog_id) {
  switch_to_blog($blog_id);
  // …取得処理…
  restore_current_blog();
}
?>

パスの前後のスラッシュまで正確に渡す必要があります(/shop/)。うまく取れないときは、get_sites()の結果をvar_dump()して実際のpathの形を確認するのが早道です。

べんりワザマルチサイトで他サイトの投稿を取得する(switch_to_blog)取得したIDで他サイトの投稿を読む方法はこちら

スラッグからIDを引くヘルパー

コードの中でIDを直書きしないための小さな関数です。

<?php
/** スラッグからサイトIDを引く(見つからなければ0) */
function mynet_blog_id_by_slug($slug) {
  foreach (get_sites(['number' => 100]) as $site) {
    if (trim($site->path, '/') === $slug) {
      return (int) $site->blog_id;
    }
  }
  return 0;
}

mynet_blog_id_by_slug('shop')のように呼べば、環境をまたいでも同じサイトを指せます。呼び出しが多い場所ではキャッシュ(set_site_transient())を挟むとより安全です。

管理画面側で判別する

管理画面のカスタマイズでも同じ関数が使えます。ただし管理画面ではget_blog_details()が「編集中のサイト」を指す点に注意します(ネットワーク管理画面ではメインサイトの文脈になります)。

<?php
add_action('admin_notices', function () {
  if (mynet_site_slug() === 'shop') {
    echo '<div class="notice notice-info"><p>ショップサイトでは商品の公開前に価格を確認してください。</p></div>';
  }
});

サイトごとに運用ルールが違う場合、管理画面に一言出しておくと問い合わせが減ります。

まとめ

  1. 判別はスラッグ(trim(get_blog_details()->path, '/')が基本。IDは環境でズレる
  2. ヘルパー関数1つにまとめ、サブドメイン型・サブディレクトリ型の差を吸収する
  3. サイトごとの違いは設定配列に集約し、見た目はbody_class+CSSに寄せる
  4. URLからIDを引くならget_blog_id_from_url()、スラッグから引くなら自作ヘルパー

「今どのサイトか」を1か所で判定できる形にしておけば、サイトが増えても分岐が散らばりません。

よくある質問

今表示している子サイトのスラッグを取得する方法は?
trim(get_blog_details()->path, '/') でサブディレクトリ型のスラッグ(例: shop)が取れます。メインサイトはパスが / なので空文字になります。サブドメイン型ではdomainの先頭部分を使います。
サイトIDとスラッグ、どちらで判定すべきですか?
スラッグ(パス)です。IDは作った順に振られるため、本番とステージングでズレることがあります。スラッグはURLと一致するので、環境をまたいでも同じ判定になります。
メインサイトかどうかを判定する関数はありますか?
is_main_site()です。引数なしで現在のサイト、is_main_site($blog_id)で任意のサイトを判定できます。メインサイトのIDはget_main_site_id()で取れます。
URLからサイトIDを調べられますか?
get_blog_id_from_url('example.com', '/shop/')で取得できます。サブディレクトリ型では第2引数のパスまで正しく渡す必要があります。