wordpressのマルチサイトで親子横断の検索ができるようにする

wordpressのマルチサイトのディレクトリ型では、標準だと親サイトは親のみ、子サイトは子のみの投稿記事内で検索する仕組みになっています。ディレクトリごとに全然違う内容の記事であれば、それはそれで便利だと思います。しかし、親子同士がある程度関連する内容の記事を投稿している場合、それでは困ることの方が多いのではないでしょうか。

wordpressのマルチサイトについて

マルチサイトの利点

普通のwordpressとマルチサイトとの大きな違いは、マルチサイトでは子サイトごとに好きなテーマなどを使えるという点です。シングルのwordpressだと、カテゴリをどれだけ増やしても同じテーマしか使えません。技術的にはプラグインなどで普通のwordpressでも同じようなことができると思いますが、そうなると管理が面倒です。マルチサイトだと標準で子サイトごとに様々な設定ができるため、活用範囲は広いでしょう。

マルチサイトの欠点

ただ、マルチサイトにも欠点はあります。それは、シングルのwordpressに比べると利用者が少ないことです。そのため、ネット上にもあまりマルチサイトに関係する情報がなかったりします。wordpressがマルチサイトを公開した当初の日本では、子サイトを順番に処理する関数の存在さえあまり知られてなかったと思います。時間と共にそれらをうまく活用したコードも見られるようになりましたけれど。

検索コードの解説

表示件数

データベース内から最大何件引っ張り出すかを設定できますが、通常は実際の記事数より多めに指定します。初期値は100件ですが、$totalNum変数で変更できます。

ページネーションの1ページ内に表示できる件数も自由に設定できます。初期値では10件にしてありますが、$pageNum変数で変更できます。

また、親サイト、子サイトのそれぞれで何件ずつ表示するかも$eachSiteNum変数で変更することが可能です。初期値は0を指定していますが、この変数での0は全件出力のことを意味します。一方、$totalNumと$pageNumで0を指定すると本当に0件となりますので注意して下さい。0以外は上記二つの変数と同じです。数値の分だけ出力されます。

コードの注意点

以下のwordpressマルチサイト用の検索コードは大分昔に筆者が作ったものです。効率の悪い部分も沢山ありますが、応用して自分なりによりよいコードにして活用頂けると幸いです。また、カテゴリーの順番を変えるプラグインと併用するとカテゴリー名をうまく取得できないケースがあります。その場合でも記事タイトルや抜粋文、URL、サムネイルなどは正常に取得できます。wordpressのカテゴリーと投稿はデータベース内で異なるテーブルで管理されているため、こういった現象が起こるのでしょう。かといって統合されても困るのですが。

尚、このコードはディレクトリ型のマルチサイトで開発しています。そのため、サブドメイン型のマルチサイトでは検証しておりません。

作成手順

まず、wordpressのご利用テーマ内に「search.php」があるかどうか確認してください。

「search.php」がある

存在すればwordpress管理画面からテーマ編集画面へ移動して後述するコードをまるごとコピーして貼り付けてください。初期状態が気に入らなければ$strでヒアドキュメントを代入していますので、ヒアドキュメント内でそのままHTMLやcssを追加変更してください。変数や関数なども入れることが可能です。

「search.php」がない

「search.php」が存在しない場合も同様で、まるごとコピーします。ただし、下記のコードの存在は必ず確認してください。このコードがないとwordpressは検索用のテンプレートだと認識してくれません。準備が出来たら、「wp-content/themes/ご利用テーマ/」内に「search.php」をFTPなどでアップロードしてください。問題がなければ動作すると思います。

<?php
/*
Template Name: Search Page
*/
?>
<?php get_header(); ?>
<div id="">
<div id="" class="">
<h1 class="post-title">「<?php the_search_query(); ?>」で検索した結果です。</h1>
<?php
// サムネイルの取得
function get_wordpress_img($cat_id_wordpress, $post_id_wordpress=null){
global $post,$blog_id;$first_wordpress_img='';
if(is_null($post_id_wordpress)){$get_wordpress_p=get_post($post_id_wordpress);}else{$get_wordpress_p = $post;}
$output = preg_match_all('/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', $get_wordpress_p->post_content, $matches);
if(isset($matches, $matches[1][0])){
$first_wordpress_img=$matches[1][0];
}
return $first_wordpress_img;
}
$totalNum=100; // データベースからの最大取得件数
$pageNum=10; // 一ページ内の表示件数
$eachSiteNum=0; // マルチサイトの親サイト子サイトそれぞれの表示件数 // 0は全件出力という意味
$multi=[];
$sites = get_sites();
foreach($sites as $site){
foreach($site as $key => $val){
// マルチサイトの全ブログIDを取得
if($key=="blog_id"){$multi_wordpress[]=$val;}
}
}
$gsq=urlencode(get_search_query());
$count1=0;
foreach($multi_wordpress as $b_id){
switch_to_blog($b_id);
$array_search_wordpress=[
's' => get_search_query(),
'posts_per_page' => $eachSiteNum, // マルチサイトの親サイト子サイトそれぞれの表示件数
];
$search= new WP_Query($array_search_wordpress);
if ($search->found_posts>0) {
foreach ( $search->posts as $post ) { setup_postdata($post);
$count1++;
if($count1 <= $totalNum){ // マルチサイト全体の出力件数
$category = get_the_category();
if(!empty($category[0]->cat_name) && !empty($cat_id_wordpress=$category[0]->cat_ID)){
$cat_name_wordpress=$category[0]->cat_name;$cat_id_wordpress=$category[0]->cat_ID;
}
$permalink=get_the_permalink();
$title=get_the_title();
$excerpt=get_the_excerpt();
$content_img=get_wordpress_img($cat_id_wordpress);
// ここがメインの出力部分ですので、好みのHTMLに成型できます
$str = <<<EOD
<div class="main-wrapper ani">
<div class="main-right">
<h2 style="margin:0 0 3px 0;padding-top:0;font-weight:bold;"><a href="{$permalink}">{$title}</a></h2>
<div style="font-size:14px;">{$excerpt}</div>
<div style="font-size:14px;"></div>
</div>
<div class="main-left" style="position:relative;font-size:13px;">
<a href="{$permalink}"><img src="{$content_img}" /></a>
<div class="trim" style="position:absolute;top:0;left:0;background-color:rgba(55,55,55,0.7);color:#ffffff;padding:2px 4px;font-size:100%;">{$cat_name_wordpress}</div>
</div>
<div style="clear:both;"></div>
</div>
EOD;
$pg_wordpress[]=$str;
}
}
}
wp_reset_postdata();restore_current_blog();
}
// 表示件数とページネーション
if(!empty($pg_wordpress)){
if(empty($_GET["pg"])){$_GET["pg"]="";}
$getpg1=(float)$_GET["pg"];
$getpg2=(float)$_GET["pg"]-$pageNum;
$c=count($pg_wordpress);
if($c!=0){$amari=$c/$pageNum;$amari=floor($amari);$amari=$amari*$pageNum;}
$style='display:block;border:1px solid black;text-align:center;padding:5px 10px;margin:2px;';
$i=0;
foreach($pg_wordpress as $key => $val){
$i++;
if($i <= $getpg1 && $i > $getpg2 || ($getpg1=="" && $i <= $pageNum)){$sty='background:red;color:#ffffff;';}else{$sty="";}
if (($i % $pageNum) == 0){$pg_link_wordpress[$i] ='<a href="?s='.$gsq.'&pg='.$i.'" style="'.$style.$sty.'">'.($i/$pageNum).' </a>';}
if(($amari+1)==$i){$amari=$amari+$pageNum;$pg_link_wordpress[$i] ='<a href="?s='.$gsq.'&pg='.$amari.'" style="'.$style.$sty.'">'.($amari/$pageNum).' </a>';}
}
$count2=0;
foreach($pg_wordpress as $ke => $va){
$count2++;
if(($count2 <= $getpg1 && $count2 > $getpg2) || ($getpg1=="" && $count2 <= $pageNum)){$search_results_wordpress[$ke]=$va;}
}
foreach($search_results_wordpress as $v){
echo $v;
}
$style='style="display:inline-block;padding:0;margin:0;"';
echo '<div style="text-align:center;">';
foreach($pg_link_wordpress as $val){
echo '<div '.$style.'>'.$val.'</div>';
}
echo '</div>';
}
if(empty($pg_wordpress)){
?>
<div>見つかりませんでした。</div>
<?php } ?>
</div><!--#-->
</div><!--#-->
<?php
//get_sidebar(); // サイドバーがある場合はコメントアウトを外して下さい
get_footer();
?>

まとめ

wordpressのマルチサイト用の検索コード、いかがでしたでしょうか。筆者もマルチサイトを初めて構築した際にプラグインでなんとか簡単にできないものかと色々楽できる方法を探索しました。海外製のものでマルチサイト用のを見つけましたが、インストールしても親サイトと各子サイトを横断して検索することはできませんでした。結局自分で作ったほうが早いと考えるに至りました。