
WordPressの話しです。
親サイトに全ての子サイトから投稿一覧を取得し時系列に並べて表示したい、という案件に対応するため四苦八苦したので自分への備忘録です。
マルチサイトが絡むとだいたいややこしくなるのですが、今回もかなりややこしかったです。
早速完成したソースから
まずは親テーマ「function.php」へ以下を追加
function get_multisite_posts( $args ) {
//サイトの取得
$number = $args['number'];
$site = array( 'site__not_in' => array( 1 ), 'number' => $number );
$blogs = get_sites( $site );
//取得件数
$limit = ( !$args['limit'] ) ? false : $args['limit'];
global $wpdb;
$sql = '';
foreach( $blogs as $blog ){
//blog切り替え
switch_to_blog( $blog->blog_id );
$str = "(SELECT posts.post_date,CONVERT(posts.post_title USING utf8mb4) AS post_title,CONVERT(posts.guid USING utf8mb4) AS guid,{$blog->blog_id} AS blog_id,%s AS blog_name ";
$str .= "FROM {$wpdb->posts} AS posts WHERE post_type='post' AND post_status='publish' AND post_date > ( NOW( ) - INTERVAL 1 DAY )) ";
$sql .= $wpdb->prepare( $str, get_blog_option( $blog->blog_id, 'blogname') );
//次のblogがあるか
next( $blogs );
if( current( $blogs ) !== false){
$sql .= "UNION ";
}
restore_current_blog();
}
$limit = ( !$limit ) ? null : $wpdb->prepare( 'LIMIT %d', $limit);
$sql .= "ORDER BY post_date DESC {$limit}";
$posts = $wpdb->get_results( $sql );
return $posts;
続いて親テーマ「index.php」へ以下を(home.phpでも可。TOPページの一番優先されているとこ)
<dl>
<?php
$args = array(
'number' => 200, // 取得する子サイトの最大数
'limit' => 15 // 表示する記事件数
);
$posts = get_multisite_posts( $args );
foreach( $posts as $post ) :
switch_to_blog( $post->blog_id );
setup_postdata( $post );
?>
<dt><span class="circle">●</span> <?php echo esc_html( $post->blog_name ); ?>(<?php the_time('m/d G:i'); ?>)</dt>
<dd><a href="<?php echo esc_html( $post->guid ); ?>" target="_parent"><?php the_title(); ?></a></dd>
<?php
restore_current_blog();
endforeach;
wp_reset_postdata();
?>
</dl>
参考にしたサイト
参考に、というかソースはほとんどここから流用させていただいたのですが、一部不要だったり、うまく行かない部分があったので、その辺は改造しています。ありがとうございます。サイレントお礼。https://securavita.net/get_multisite_posts/
ポイント
・get_sites は number を指定しないと100サイトまで
子サイトが100件超えるなんて普通はないと思いますが、超える場合は number の指定がないと取得できない子サイトが出てしまいます
SQLで以下のエラーが発生する場合
Illegal mix of collations for operation ‘UNION’ ~
collations(照合順序)とやらが一致しないのでUNIONできないよ、ということらしいです。COLLATE 使って取得したらいけるよ、という記事をみましたが、utf8とutf8mb4の違いはCOLLATEできない??ようでした。
https://nob-log.info/2014/07/10/illegal-mix-of-collations-for-operation-union/
解決方法としては、僕はCONVERT(カラム名 USING utf8mb4) とカラムの文字コードを変更してみたら動きました。文字コードでいいのか?collationsじゃなかったか?という疑問は残る。
日にちは指定して取得した
post_date > ( NOW( ) – INTERVAL 1 DAY )
WHEREで過去1日という条件を足しました。これがないと途方もない記事数を取得しちゃうので。
今回の作業で覚えておきたいことメモ
MySQLで照合順序を確認する方法
https://odasusu.hatenablog.com/entry/2014/02/21/132203
キャスト関数と演算子
https://dev.mysql.com/doc/refman/5.6/ja/cast-functions.html

コメントを残す