Wordpressのマルチサイトで全ブログを対象とした検索をする

## 概要
WordPressのマルチサイトでは、全ブログを対象とした検索ができない。
そこで全ブログを検索するコードを作成しました。

## 方針
- switch_to_blog()はペナルティが大きいらしく、サーバに負荷が掛かるようなのでやめる。
- カテゴリー、タグも検索対象とする。Wordpressデフォルトでは、本文、記事タイトルのみが検索対象のため。

## 作成したコード
wp-content/themes/(テンプレート)/search.php を次のようにしました。

```php:search.php
<?php get_header(); ?>
<!?// ここから書き換え----------------------------------------------- //?>
<?php
global $wpdb;//mysqlのデータベース情報を格納しているグローバル変数$wpdb
$searchfor = get_search_query(); // 検索キーワード取得
?>
<h2>「<?php echo $searchfor; ?>」の検索結果</h2>
<?php
$sql="SHOW TABLES FROM $wpdb->dbname"; //テーブル一覧を取得するSQL文を作成
$res_rows = $wpdb->get_results($sql); //テーブル一覧を$res_rowsに格納
if(!$res_rows){
    echo "【データベースエラー】テーブルリストの取得に失敗しました<br />\n";
    echo "MySQL Error: ".mysqli_error();
    exit;
}
$siteurl_chk_array=array(); //検出される記事のURLを重複を除外するためのチェック用配列(初期化)
foreach($res_rows as $data) { //$data にテーブルを格納するループ
    // $objectToArray = (array)$data;
    // print_r(  array_values($objectToArray)[0] );
    // オブジェクトを配列にして値取得
    $tablename = array_values( (array)$data )[0]; //テーブル名取得
    if( preg_match("/_posts/",$tablename) ) { //postsテーブルループ
        if( !preg_match("/v_posts/",$tablename) ) {
            # print($tablename);
            $siteid="";
            if (preg_match('/wp_(\d{1,4})/', $tablename, $tmp_match)){
                $siteid = $tmp_match[1]."_";
            }
            $term_relationships = "wp_".$siteid."term_relationships";
            $term_taxonomy = "wp_".$siteid."term_taxonomy";
            $terms = "wp_".$siteid."terms";
            $options = "wp_".$siteid."options";

            // 検索用SQL
            // 検索対象: 公開された記事で、記事本文(post_content), 記事タイトル(post_title), 
            // 記事カテゴリ/タグ名(wp_x_term.terms ), 抜粋(wp_x_term_taxonomy.description)
            //   → → 記事本文(post_content), 記事タイトル(post_title)で検索して見つかる記事 
            //            または、記事カテゴリ/タグ名を検索し該当の term_id を使用する記事
            $searchquery_posts = 
            "SELECT * FROM " .$tablename. " 
            WHERE post_status = 'publish' AND
            (post_type = 'post' OR post_type = 'page') AND 
            (post_content LIKE '%" .$searchfor. "%' OR post_title LIKE '%" .$searchfor. "%'
                OR ID IN (
                    SELECT distinct r.object_id
                    FROM ".$term_relationships." AS r
                    INNER JOIN ".$term_taxonomy." AS tt ON r.term_taxonomy_id = tt.term_taxonomy_id
                    INNER JOIN ".$terms." AS t ON tt.term_id = t.term_id
                    WHERE t.name LIKE '" .$searchfor. "'
                OR t.slug LIKE '" .$searchfor. "'
                OR tt.description LIKE '" .$searchfor. "'
                )
            )";
            // 検索SQLを実行
            $result_posts = $wpdb->get_results($searchquery_posts, ARRAY_A);
            $siteurl=""; //各ブログのURL
            if($result_posts===null){
                continue;
            }elseif ($result_posts) {
                // 各ブログのURLを見つけるSQL
                $searchquery_siteurl = "SELECT option_value FROM " .$options. " WHERE option_name = 'siteurl' ";
                $siteurl = $wpdb->get_var($searchquery_siteurl);
                if($siteurl===null){
                    continue;
                }
            }
        }
    }
    // print_r($result_posts);
    foreach($result_posts as $row)  {//検索結果を表示するHTMLを出力
        $tmpurl = $siteurl. "?page_id=" .$row['ID'];
        if (!in_array($tmpurl, $siteurl_chk_array)){
            echo "<div class='searchlink'><a href='";
            print($tmpurl);
            echo "'>「";
            print($row['post_title']);
            echo "」</a></div>";
            print(mb_substr(strip_tags($row['post_content']),0,200));//contentからHTMLタグを取り除き200文字のみ表示
            echo "<br />\n";
            // 記事のURLを重複を除外するためのチェック用配列に追加
            $siteurl_chk_array[] = $tmpurl;
        }
    }
}
// print_r($siteurl_chk_array);
?>
<!?// ここまで書き換え----------------------------------------------- //?>
<?php get_footer();
```
## 参考にしたサイト
- 流れはこの↓サイトのコードを参照にました（mysql_connect()などが、php5用だったため、php7で対応できるようにしました）。
  [https://d7r.com/2197](https://d7r.com/2197)

- [Wordpress php からDBの情報取得方法](https://qiita.com/yousan/items/f29e7010a1384c1e1206#%E5%89%8D%E7%BD%AE%E3%81%8D)

- [カテゴリー名、タグ名を検索対象とするのに参照](http://taneakashi.ad-mk.com/wordpress-site-search-customize.html)


## 課題
- 検索結果が、一覧ですべて表示されます。ページネイション機能を入れて、ページ送りが必要です。
  - → これは必須の機能ですね。。。
- 自作のHTMLのためWordpressデフォルトの検索結果ページデザインと異なってしまいます。検索結果ページをブログのデザインに合わせる必要があります。
- 複数語の検索には未対応です。検索文字が「AAA, BBB, CCC」とあったら、「AAA」, 「BBB」, 「CCC」の全部の単語が見つかるように検索ではなく、「AAA, BBB, CCC」という文字列で検索します。
- 検索結果は、見つかった順です。検出件数の多い順などでは、ありません。