マルチサイト内で複数のブログ記事を表示するコード
ひとつのWordpress中のメイン・サブ関わらず、複数のブログの混合した記事を一覧として出したい場合があります。
複数のブログの記事を載っける場合、よくあるのはRSSを結合、参照して表示するあれですね。
それをWordpressの方でRSSを使用せずに何とかできないかとかねがね思ってました。
ですが、WordpressでMovableTypeのようにマルチサイト間の記事をごっちゃで取得するテンプレートタグはないみたいです。
WordPressマルチサイト内の別のブログ記事を単一で表示する場合、以下の書き方でいけますが・・・。
<?php switch_to_blog(10); $entries = get_posts(); foreach($entries as $entry){ global $post; $post = $entry; setup_postdata($post) ?> <article id="post-<?php the_ID(); ?>" class="entry"> <header> <time><?php the_time('Y-m-d g:i a'); ?></time> <h1><?php the_title(); ?></h1> </header> <section><?php the_content(); ?></section> <footer> <p class="categories"><?php the_category(); ?></p> <p class="tags"><?php the_tags(''); ?></p> </footer> </article> <?php wp_reset_postdata(); } restore_current_blog(); ?>
これだと複数のブログを混合した記事は出すことができない。
switch_to_blog()は一つのブログに切り替えるテンプレート関数ですし、そもそも、どこにWP_Postのようなデータが入ってくるんだ?ってなると思います。
そこで、複数ブログを取得できるように独自関数を作成しました。
SQLをちらっとでもかじったことがある人は、仕組みについては多分わかると思いますので解説は割愛。
とりあえずこの書き方で動くと思います。
WordPressマルチサイト内のブログ(単体)の記事一覧を表示する
functions.phpと複数ブログの記事一覧を表示したい箇所に記述します。
functions.phpに記載
/* 複数のブログを参照してWP_Post状のデータを作成する関数 */ function get_multisite_posts($a_site_id = array(1), $a_per_post = 10, $a_order_by = 'post_date DESC'){ global $wpdb; $str = ''; $query; $sites_id = ($a_site_id == null || $a_site_id == 0 || $a_site_id == '') ? array(1) : $a_site_id ; $per_post = ($a_per_post == null || $a_per_post == 0 || $a_per_post == '') ? 10 : $a_per_post; $order_by = ($a_order_by == null || $a_order_by == 0 || $a_order_by == '') ? 'post_date DESC' : $a_order_by; foreach($sites_id as $site_key => $site_id){ switch_to_blog($site_id); $str .= "(SELECT *, $site_id AS site_id FROM $wpdb->posts WHERE post_type = 'post' AND post_status = 'publish')"; $str .= ($sites_id[$site_key + 1]) ? ' union ' : ' '; restore_current_blog(); } $str .= "ORDER BY $order_by LIMIT $per_post"; $query = $wpdb->get_results($str); return $query; } /* ループ中の記事データをセットする関数 */ function get_multisite_posts_prep($a_entry = false){ $entry = ($a_entry == null || $a_entry == 0 || $a_entry == '') ? false : $a_entry; if(!$entry){ wp_reset_postdata(); restore_current_blog(); }else{ global $post; $post = $entry; switch_to_blog($a_entry->site_id); setup_postdata($post); } }
記事を一覧表示したい場所に記載
<?php $entries = get_multisite_posts(array(1, 2)); //ブログIDは配列で指定 foreach($entries as $entry){ get_multisite_posts_prep($entry); //始端では引数はforeachの内部配列に合わせる ?> <article id="post-<?php echo $entry->site_id; ?>-<?php the_ID(); ?>" class="entry"> <header> <time><?php the_time('Y-m-d g:i a'); ?></time> <h1><?php the_title(); ?></h1> </header> <section><?php the_content(); ?></section> <footer> <p class="categories"><?php the_category(); ?></p> <p class="tags"><?php the_tags(''); ?></p> </footer> </article> <?php get_multisite_posts_prep(); //終端では引数なしで現データをリセットする } ?>
これで、ひとつのWordpressのマルチサイト内で複数のブログ記事を表示することができます。
キモとなるのはやはり簡素な手順とSQL発行でWP_Post状のデータが取得できること。
$wpdbめっちゃ便利ですね~。
SQLのテーブルがわかっていなくてもget_posts()のオブジェクトと同じと言えば、「ああ」となるでしょう。
いやはやWordpressってよくできてますね。
あ、引数忘れてた。
get_multisite_posts()の呼出しの際に、引数はブログIDの他、記事数が指定可能。
ソート用の引数も設置してますが、SQLのorder by形式で指定するので、あんま指定しないほうがいいかもしれない。
ちなみにSQLでクエリを直接作っている性質上、Intuitive Custom Post Order等の記事ソートプラグインには対応していません。
テーブルを外部結合してソート条件を少し変えてあげれば、行けそうな気もしますが。