web-dev-qa-db-ja.com

処理前に検索文字列を取得(および変更)するためのフック

検索クエリをWordpressで実行する前に傍受しようとしています。私はたくさんのことを試してみましたが、それだけでは動作しません。

したがって、たとえば、ユーザーが検索用語RED SHOESを入力したとします。私は、REDの発生をすべてROSSOに変更したいと思います(これはこれよりも複雑ですが、アイデアを得ることができます。翻訳と関係があります)。

私はこのようなものを見ています:

function modify_search_vars($search_vars) {

    $change_to = array(
        "blue"  => "blu",
        "red"   => "rosso",
    );

    if ( !empty($search_vars['s']) ) {
        $search_vars['s'] = str_ireplace(array_keys($change_to), array_values($change_to), $search_vars['s']);
    }
    return $search_vars;

}
add_filter('request', 'modify_search_vars', 99);

ここで任意の助けやアイデアは大歓迎です!ありがとうございます。

1
arathra

検索へのより深い「インジェクション」を達成し、ユーザーができるだけ早く検索したものをキャッチするために、WP_Queryクラスを見て、それがどのように投稿のためのクエリを扱うのかを見なければなりません:

そのparse_query関数の週に、それはクラス全体に、実際にはクエリが "検索"であることを知らせるためにフラグを使用しています。驚くことではないが、それはクエリ内でsを探します。

if ( isset( $this->query['s'] ) ) {
    $this->is_search = true;
}

素晴らしいですが、do_action( 'super_important_hook' . $handle_that_we_could_use, $query)のように「名前ごと」に、この大きくて重要なプロセスに取り組むことができるようなアクションはありません。

parse_queryの前に起動するpre_get_postsがあります。

function replace_search( $query_object )
{
    if( $query_object->is_search() ) {
        $raw_search = $query_object->query['s'];

        $replacement = str_replace( 'red', 'rosso', $raw_search );

        if( $replacement ) {
            $query_object->set( 's', $replacement );
        }
    }
}

add_action( 'parse_query', 'replace_search' );

...そしてそれはうまくいきます!可能な限り早くフックして、クエリが発生したらすぐに変更します。 set関数はまさにそれが言うことをします、それはクラスのために使われるどんな内部変数のためのセッターです。

ちなみに、parse_tax_queryを含む$this->parse_tax_query()は、同じparse_queryをアクションに渡すparse_tax_queryparse_query()関数内で呼び出されるので、フックWP_QueryWP_Query Objectの前に起動します。 parse_queryがこの種の振る舞いにフックするのがもっと一般的であるように思われるので、私はこのフックを使いません。

まず - 覚えておいてください /プラグインが検索文字列を探すためにこのフックを使わない限り、彼らはこれらのフックの前に来る$_REQUEST['s']を探すかもし​​れず、その時点で変更されるかもしれません。とにかく、ユーザーの検索がシステムに入る最も早い時点は$_REQUEST['s']なので、できるだけ早くこの値にフックする必要があるでしょう、私の答えはここではかなり良いですが、私は遊ぶときもっと考慮すべき方法があると思います検索、そしてもちろん、それらの関数がより高い優先順位を持ち、それらが文字列を他の何かに変換するのであれば、あなたは運命にあります。

明らかに、あなたはもっと洗練された "置き換え"メカニズムを持っているでしょうが、それはあなたが必要とするフックを示すためだけのものです。

次に、これらのアクションについての興味深い点は、それらが参照によってオブジェクトを渡すことです。

/**
 * Fires after the main query vars have been parsed.
 *
 * @since 1.5.0
 *
 * @param WP_Query $this The WP_Query instance (passed by reference).
 */
do_action_ref_array( 'parse_query', array( &$this ) );

これが何を意味するのか、そして心に留めておくことが賢明です - あなたのスクリプトがparse_queryにフックするときあなたがするすべての修正はそれがフックされる次のスクリプトに渡される実際のクラス自体に反映されます。そのクラスのライフサイクル全体。これが良い設計上の選択であったかどうかはわかりません。「なぜこの変数はリセットされないのですか。新しいクラスインスタンスです」という場合がある場合に備えて、このクラスはシングルトンのように動作します。そうではありませんので、WPが終了するまで同じクラスでプレーしていることを覚えておいてください。それに行ったすべての変更は、後に続くものすべてによって使用されます。 WP_QueryがWP自体の実際のコアなので、あなたがすること、これを使用する多くのプロセス/プラグインがあります。


可能な限り遅く「フック」しようとしているのであれば、クエリ自体は変更されますが、フックするのは遅くなるでしょう。テーマ/プラグインは、表示される前にこの値で遊ぶ可能性があります。

add_filter( 'get_search_query', function( $user_search_query ) {
    $replacement = str_replace( 'red', 'rosso', $user_search_query );

    if( $replacement ) {
        return $replacement;
    }

    return $user_search_query;
}, 999);

あなたが探しているフックはget_search_queryです。しかし、これにはたくさんのプラグインや機能があることを知っておいてください。ですから、これを変更することによる影響に注意してください。それを使用する主な機能は次のとおりです。

/**
 * Displays the contents of the search query variable.
 *
 * The search query string is passed through esc_attr() to ensure that it is safe
 * for placing in an html attribute.
 *
 * @since 2.1.0
 */
function the_search_query() {
    /**
     * Filters the contents of the search query variable for display.
     *
     * @since 2.3.0
     *
     * @param mixed $search Contents of the search query variable.
     */
    echo esc_attr( apply_filters( 'the_search_query', get_search_query( false ) ) );
}

WP Coreのgeneral-template.phpから。このパラメータはget_search_queryからフィルタに渡されます。これは$_REQUEST['s']にあるものをすべて取得するための単純なラッパーです。

2
coolpasta