WordPress をマルチサイトで運用するとき、複数のサブサイトの投稿をまとめてメインサイトに表示したい場合があります。

今回、メインサイトとサブサイト(ネットワーク全体)の投稿を時系列にまとめ、メインサイトのフロントページ(ウェブサイトのホームページ)に最新の10件を表示し、一覧のリンクから遷移するページでは全件を20件毎にページ分割して表示、更にネットワーク全体の投稿をまとめた RSS を配信するという実装を試みました。

WP Over Network プラグインを利用して実装したのですが、ページネーションでつまづきました。試行錯誤のうえ、最終的にどうにか実装できたので記しておきます。

メインサイトのフロントページに新着10件を表示

これは上述のプラグインを利用することで、すんなりと実装できました。

<ul>
<?php
$args = array(
  'post_type' => 'post',
  'post_status' => 'publish',
  'numberposts' => 10
);
$posts = wponw::get_posts($args);
global $post;
foreach ( $posts as $post ):
  switch_to_blog( $post->blog_id );

  各投稿を表示する記述

  restore_current_blog();
endforeach;
wp_reset_query();
?>
</ul>

私の場合、各投稿を表示する記述は別ファイルにして、それぞれのテンプレートにインクルードしているのですが、メインサイトのみで各投稿にサイトの名前を表示する必要がある場合、ループの中で表示する先がメインサイトかどうかを判断する必要があります。その場合、ループの手前で $main_site = 1 といった変数を定義しておき、各投稿を表示する記述の中で、

global $main_site;
if ( $main_site == 1 ){
  echo '<span class="site">'. get_bloginfo('name'). '</span>'
}

のようにして、メインサイトのみで各投稿のサイトの名前を表示することができます。

一覧ページに20件毎にページ分割して表示

次に、一覧ページでは全件を20件毎にページ分割して表示します。

WP Over Network プラグインの日本語の説明「WP Over Network をリリースしました。」によると、

affect_wp_query trueを指定すると $wp_query を変更します。$wp_query に依存するプラグイン(例:WP_PageNavi)を利用する際に利用する。

ということなので、配列の中に 'affect_wp_query' => true を追加します。

そして、このプラグインの関数 numberposts は取得件数なので、全件という意味で -1 を設定してみましたが、2ページ目以降が正しく表示されないなど、ページネーションが機能しません。これは1ページあたりの取得件数ということのようです。

それでも正しく表示できず、最終的に、表示設定の「1ページに表示する最大投稿数」を1件にする必要がありました。

<ul>
<?php
$args = array(
  'post_type' => 'post',
  'post_status' => 'publish',
  'numberposts' => 10,
  'affect_wp_query' => true
);
$posts = wponw::get_posts($args);
global $post;
foreach ( $posts as $post ):
  switch_to_blog( $post->blog_id );

  各投稿を表示する記述

  restore_current_blog();
endforeach;
?>
</ul>

ページネーションを表示する記述

<php
wp_reset_query();
?>

RSS を配信する

WordPress の RSS のテンプレートは wp-includes ディレクトリの中にあります。WP Over Network プラグインを使ってこのテンプレート(今回は feed-rss2.php)の投稿を取得する部分を書き替えればよさそうですが、サブサイトではそのサイトの投稿のみを RSS 配信する必要があります。

そこで、WordPressのマルチサイトで子サイトのフィードを取得するの記事を参考にさせていただき、テーマディレクトリにカスタマイズした feed-rss2.php を置き、メインサイトの場合のみ、これを読み込むようにしました。

feed-rss2.php をコピーしてテーマディレクトリに置き、後半を以下のように書き替えます。

81行目

// while( have_posts()) : the_post();
$args = array(
  'post_type' => 'post',
  'post_status' => 'publish',
  'numberposts' => 10
);
$posts = wponw::get_posts($args);
global $post;
foreach ( $posts as $post ):
  switch_to_blog( $post->blog_id );

元の115行目

<?php restore_current_blog();
 endforeach; //endwhile; ?>

function.php に以下を追記します。

if ( is_main_site() ){
  remove_filter('do_feed_rss2', 'do_feed_rss2', 10);
  function custom_feed_rss2(){
    $template_file = '/feed-rss2.php';
    load_template(get_stylesheet_directory(). $template_file);
  }
  add_action('do_feed_rss2', 'custom_feed_rss2', 10);
}

これでとりあえず思っていた実装が可能となりましたが、マルチサイトの連携が Movable Type のマルチブログ機能のように簡単にできるとよいなと感じたのでした。