Multisite (ネットワーク、MU、MultiUser) 検索
SearchWP はサイトを横断する Multisite/Network 検索を実行できます。実装に関して言及/考慮すべき点がいくつかあります。
注意: 認識しておくべき重要な制限があります!
概要
SearchWP ではサイトを横断する検索が可能です。サイトを横断する検索には、どのサイトのどのエンジンでも使用できます。
注意: SearchWP のエンジンは、各サブサイトでインデックス化されるものを制御します。検索に使用しているエンジンが、検索対象のサブサイトのエンジンとは異なるソース/属性/ルールを持っている場合、結果が正確でない可能性があります。
たとえば、検索に使用しているエンジンに投稿が追加されていても、サブサイトに投稿が有効になっているエンジンがない場合、そのサブサイトからは投稿は返されません。
包括的なサイト横断検索のためには、すべてのサイトで類似の設定と適用可能なエンジンを共有していることを確認してください。
実装の詳細
Multisite 環境では、SearchWP はネットワーク全体の包括的な検索インデックスを構築します。デフォルトでは、SearchWP は現在のサイトのエントリに結果を制限します。
\SearchWP\Query を使用して、ネットワーク内の複数のサイトを横断する検索を実行できます。その際は、site パラメータを次のようにカスタマイズします。
- サイト ID の配列(またはサイト ID のカンマ区切り文字列)
- ネットワーク上のすべてのサイトを検索するには
'all'
重要: 理解すべき主な概念は、SearchWP のエンジンがネットワーク内のすべてのサイトに対してどのコンテンツがインデックス化されるかを決定するということです。
これは、\SearchWP\Query が現在のサイトのエンジンを使用して検索を実行するため重要です。現在のサイト(SITE A)のデフォルトエンジンに次のソースが含まれていると仮定します。
- 投稿
- ページ
この例のネットワークには、次のソースを含むデフォルトエンジンを持つ 2 番目のサイト(SITE B)があります。
- 投稿
SITE A でそのデフォルトエンジンを使用して \SearchWP\Query を実行している場合、SITE B のデフォルトエンジンにページが追加されていないため、SITE B のページは返されません。
これは、ページが SITE A のデフォルトエンジンに追加されているため、直感に反するように思えるかもしれませんが、SITE B のエンジンがそのサイトでインデックス化されるものを定義および制御しています。
推奨されるエンジン設定
上記を踏まえ、共通の設定を共有する各ネットワークサイトで 補足的なエンジン を利用できます。
または、ネットワーク内のすべてのサイトで共通の最小公倍数となるエンジンを\SearchWP\Queryで使用するようにネットワークが設定されていることを確認することもできます。
Multisite の検索結果の処理
\SearchWP\Queryでは、fieldsパラメータを使用して結果の返却方法を指定できます。
デフォルトでは、結果は、それぞれ'id'、'source'、'site'、'relevance'のプロパティを持つオブジェクトの配列として返されます。
この形式は、Multisiteの検索結果に最も役立ちます。なぜなら、各結果の正確な詳細を取得するために、必要に応じてswitch_to_blog()を使用できるからです。
ただし、他のサポートされている形式を使用することを選択した場合、重要なsite ID情報が含まれない可能性がありますので、Multisiteの検索を構造化する際にはこの点に注意してください。
注意:これは、fieldsを'all'に設定した場合に特に適用されます。これにより、各結果がネイティブ形式(例: \WP_Post)で返されます。結果の出力でなされた仮定(例: get_permalink()の使用)は、現在のサイトに基づいています。結果が返されたサイトからではなく、必ずしもそうではありません!
それを考慮すると、fieldsのデフォルト値を使用し、必要に応じて手動でswitch_to_blog()(およびそれに続くrestore_current_blog())を使用することが常に推奨されます!
例
クロスサイトのMultisite検索を実装するには、主に2つの方法があります。
- ネットワーク内のサイトでのネイティブ/デフォルト検索をオーバーライドする
- 専用のクロスサイトMultisite検索をセットアップする
前者はより一般的かもしれませんが、より直接的な専用検索のセットアップよりも少し複雑です。どちらのオプションもここで説明します。?
デフォルトのオーバーライド
Multisiteサイトのデフォルト検索動作をオーバーライドしてネットワーク全体を検索したい場合は、ネイティブサイトの引数をオーバーライドしてそれを行うことができます。
例:大学があり、「メイン」サイトと、さまざまな学校/学部などの多くのMultisiteサブサイトがあるとします。メインサイトの検索をオーバーライドして、Multisiteインストール全体を検索したいとします。すべてのデフォルトエンジンは、Multisiteネットワーク全体で同じです。
実行する手順は2つあります。
- ネットワーク全体を検索するためにSearchWPに送信される引数をフィルタリングする
- サイトの変更に対応するために検索結果テンプレートを更新する
メインサイト検索の引数をフィルタリングする
ネイティブ検索結果ページをカスタマイズしているため、searchwp\native\argsフックを使用して、ネットワーク全体を検索したいことをSearchWPに伝えます。
All hooks should be added to your custom SearchWP Customizations Plugin.
| <?php | |
| // @link https://searchwp.com/documentation/multisite/ | |
| // Tell SearchWP to search the entire Multisite network when searching on the main site. | |
| add_filter( 'searchwp\query\args', function( $args, $query ) { | |
| // If this is not site 1, bail out. | |
| if ( 1 !== get_current_blog_id() ) { | |
| return $args; | |
| } | |
| // Search sites with ID 1, 2, 3. | |
| $args['site'] = [1,2,3]; | |
| // Retain site info in results. | |
| $args['fields'] = 'default'; | |
| return $args; | |
| }, 10, 2 ); |
また、SearchWPにdefaultの結果(WP_Postではなく)を返すように指示していることに注意してください。これはステップ2につながります。
検索結果テンプレートの更新
ステップ1では、SearchWPにネットワーク全体を検索するように指示し、結果をWP_Postオブジェクトとしてフォーマットするのではなく、実行時に適切な結果を生成するために必要なサイト情報を含む元の形式で結果を保持するように指示しました。
SearchWPでフォーマットされた結果を考慮するために、テーマのsearch.php検索結果テンプレートの出力のループを更新する必要があります。
| <?php | |
| // @link https://searchwp.com/documentation/multisite/ | |
| global $post; | |
| $current_blog_id = get_current_blog_id(); | |
| get_header(); | |
| if ( have_posts() ) { | |
| while ( have_posts() ) { | |
| the_post(); | |
| // Search Results may be formatted as SearchWP results | |
| // because we're searching cross-site on the main site. | |
| if ( 1 === $current_blog_id ) { | |
| if ( $current_blog_id !== $post->site ) { | |
| switch_to_blog( $post->site ); | |
| $post = get_post( $post->id ); | |
| get_template_part( 'search-result' ); | |
| restore_current_blog(); | |
| } else { | |
| $post = get_post( $post->id ); | |
| get_template_part( 'search-result' ); | |
| } | |
| } else { | |
| get_template_part( 'search-result' ); | |
| } | |
| } | |
| } else { | |
| get_template_part( 'template-parts/content/content-none' ); | |
| } | |
| get_footer(); |
結果テンプレートは引き続きループに基づいていることに注意してください。ただし、サイトの変更の可能性に対応するために、サイト1(メインサイト)で結果を出力している場合の動作をカスタマイズしています。
また、テンプレートパーツが結果を出力するために使用されていることに注意してください。ただし、結果が別のサイトから返された場合は、restore_current_blog()を呼び出す前にテンプレートがインクルードされます。
これは、get_permalink()などの関数呼び出しが、次の結果を出力するためにメインサイトに戻る前に、適切なコンテキストで実行されることを保証するために必要です。
補足的なエンジンを使用する
専用のマルチサイトクロスサイト検索を実装する場合、同じ手順に従って補足エンジンを作成することができます。
補足エンジンを設定したら、まず検索の実行をカスタマイズして、マルチサイトネットワーク全体を検索できます。
| <?php | |
| // ... this overrides the \SearchWP\Query instantiation found | |
| // @link https://searchwp.com/documentation/search/supplemental-engine/ | |
| // e.g. $search_page is defined in the full snippet, this solely | |
| // replaces the query to search across sites and return 'default' results. | |
| $searchwp_query = new \SearchWP\Query( $search_query, [ | |
| 'engine' => 'supplemental', // The Engine name. | |
| 'fields' => 'default', // Retain site ID info with results. | |
| 'site' => 'all', // Search all sites. | |
| 'page' => $search_page, | |
| ] ); |
行われた2つの編集は次のとおりです。
fieldsを定義して、defaultフィールド(サイトID情報を含む)を返します。allサイトを検索するように指定します。
補足エンジンの実装に変更を加えたら、SearchWPはマルチサイトネットワーク全体を検索し、defaultの結果を返します。そのため、各結果が別のサイトであるかどうかを確認するように、結果の出力を更新する必要があります。
注意:簡潔にするために、このスニペットは、完全な補足エンジンの実装例の結果出力のみを更新します。
| <?php | |
| // ... this snippet overrides the results output found | |
| // @link https://searchwp.com/documentation/search/supplemental-engine/ | |
| // so as to account for results that are from a different Multisite site. | |
| // This is not a full and complete example, it shows only the customization | |
| // to the results output to account for site changes. | |
| // Track the current blog ID. | |
| $current_blog_id = get_current_blog_id(); | |
| ?> | |
| <?php if ( ! empty( $search_query ) && ! empty( $search_results ) ) : ?> | |
| <?php foreach ( $search_results as $search_result ) : ?> | |
| <article class="page hentry search-result"> | |
| <?php | |
| // Track whether we switched sites for this result. | |
| $switched_site = false; | |
| // Do we need to switch to the proper site for this result? | |
| if ( $current_blog_id !== $search_result->site ) { | |
| switch_to_blog( $search_result->site ); | |
| $switched_site = true; | |
| } | |
| // Output the result based on SearchWP Source. | |
| switch( $search_result->source ) { | |
| // Posts and Pages. | |
| case 'post' . SEARCHWP_SEPARATOR . 'post': | |
| case 'post' . SEARCHWP_SEPARATOR . 'page': | |
| $post = get_post( $search_result->id ); | |
| ?> | |
| <header class="entry-header"><h2 class="entry-title"> | |
| <a href="<?php echo get_permalink(); ?>"><?php the_title(); ?></a> | |
| </h2></header> | |
| <div class="entry-summary"><?php the_excerpt(); ?></div> | |
| <?php | |
| wp_reset_postdata(); | |
| break; | |
| // Users. | |
| case 'user': | |
| ?> | |
| <header class="entry-header"><h2 class="entry-title"> | |
| <a href="<?php echo get_author_posts_url( $search_result->id ); ?>"> | |
| <?php echo esc_html( get_the_author_meta( 'display_name', $search_result->id ) ); ?> | |
| </a> | |
| </h2></header> | |
| <div class="entry-summary"> | |
| <?php echo wp_kses_post( get_the_author_meta( 'description', $search_result->id ) ); ?> | |
| </div> | |
| <?php | |
| break; | |
| } | |
| ?> | |
| </article> | |
| <?php | |
| // If we switched sites, switch back! | |
| if ( $switched_site ) { | |
| restore_current_blog(); | |
| } | |
| ?> | |
| <?php endforeach; ?> | |
| <?php endif; ?> |
このスニペットセグメントでは、SearchWPから返された結果の形式(ネイティブの結果オブジェクトの代わりにdefault)に注意を払っていることがわかります。これには、各結果の発信元サイトに関する必要な情報が含まれています。
結果を反復処理する際に、必要に応じてswitch_to_blog()を使用し、各結果のsource、site、およびidを利用して、任意のSearchWPソースからの結果を引き続き出力できます。
多くの関数(例:get_permalink())は正しいサイトコンテキストで実行する必要があるため、restore_current_blog()を呼び出す前に、各結果のすべての関連データを(そしてほとんどの場合、必要になります)出力する必要があることを覚えておいてください。可能な限り遅くrestore_current_blog()(該当する場合)を呼び出すことが常に最善の選択です。

