web-dev-qa-db-ja.com

投稿を検索する方法 OR タイトル OR コンテンツ OR 著者?

カスタムメタの検索に関する多くの投稿と質問を調べましたが、投稿を検索し、検索クエリが著者名と一致する場合はそれらも含めたいと思います。

私は次のようなコードを思い付きましたが、うまくいきません。何らかの理由で、ステータスが "revision"の投稿を返します

まず、3つの関数をそれぞれのフックにフックしました。

add_filter('posts_join', 'custom_posts_join' );
add_filter('posts_groupby', 'custom_posts_groupby' );
add_filter('posts_where', 'custom_posts_where' );

それから、それぞれの機能を進めます。

custom_posts_join

function custom_posts_join($join){
    global $wpdb;
    if( is_search() && !is_admin()) {

        $join .= " LEFT JOIN $wpdb->postmeta ON $wpdb->posts.ID = $wpdb->postmeta.post_id ";
    }
    return $join;
}

custom_posts_groupby

function custom_posts_groupby( $groupby ) {
    global $wpdb;
    if( is_search() && !is_admin()) {

        $groupby = "$wpdb->posts.ID";
    }
    return $groupby;
}

custom_posts_where

function custom_posts_where( $where = '' ){
    if ( is_search() && !is_admin()) {
        global $wpdb;

        $search = ( isset($_GET["s"]) ) ? sanitize_text_field($_GET["s"]) : false ;
        $search = (string)$search;

        $users = $wpdb->get_results( "SELECT user_id FROM $wpdb->usermeta WHERE meta_key = 'first_name' AND meta_value = '$search'",OBJECT_K  );

        foreach ($users as $user)
        {
            $users_ids.=$user->user_id.','; 
        }
        $users_ids = rtrim($users_ids, ',');

        $where .= " AND ( ($wpdb->posts.post_author IN ({$users_ids})) 
               OR ($wpdb->posts.post_title LIKE '$search')
               OR ($wpdb->posts.post_content LIKE '$search') )
            AND $wpdb->posts.post_type = 'post'
            AND $wpdb->posts.post_status = 'publish'";  

        }
    return $where;
}
2
Gixty

いくつかの努力と研究の後、私はついにこの実用的な解決策を思い付きました。

このコードを改良して、代わりの答えを投稿してください。何らかの理由で、クエリが複数回実行されているようです(私の場合は3〜4回)。

ここでは、posts_searchposts_joinおよびposts_groupbyの3つのフックを使用しています

機能 custom_search_posts は、用語とユーザーを一緒に検索することを可能にします。

- ユーザーと用語を検索します。たとえば、 Money というユーザーによる投稿がある場合 Smith Smith money を検索すると、結果が投稿に表示されます。注:著者名はtermよりも先にくる必要があります。

- ユーザーのみを検索(usermetafirst_name OR last_name

- 用語だけで検索する(タイトルのみ)。

- 一度に複数のユーザーを検索することもできます。

function custom_search_posts( $search, &$wp_query )
{
    global $wpdb;
    if ( empty( $search ) )
        return $search; // exit if search is empty

    $q = $wp_query->query_vars;
    $n = ! empty( $q['exact'] ) ? '' : '%';
    $search = '';
    $searchand = '';

    add_filter('posts_join', 'custom_posts_join' );
    add_filter('posts_groupby', 'custom_posts_groupby' );   
    foreach ( (array) $q['search_terms'] as $term ) {
      $user_args = array( 
       'meta_query' => array(
        'relation' => 'OR',
          array(
            'key'     => 'first_name',
            'value'   => $term,
            'compare' => 'LIKE'
        ),
          array(
            'key'     => 'last_name',
            'value'   => $term,
            'compare' => 'LIKE'
        )
        ));
        $user_query = new WP_User_Query( $user_args );
        $users = $user_query ->get_results();
        $term = esc_sql( like_escape( $term ) );
        $search .= "{$searchand} $wpdb->posts.post_title LIKE '{$n}{$term}{$n}' ";
        if (!empty($users)) {
            foreach ($users as $user) {   
                $user_id = $user->ID;    
                $search .= " OR $wpdb->posts.post_author IN ('{$user_id}') ";           
            }                   
        }       

        $searchand = ' AND ';
    }
    if ( ! empty( $search ) ) {
        $search = " AND ({$search}) ";
        if ( ! is_user_logged_in() )
            $search .= " AND ($wpdb->posts.post_password = '') ";
    }

    $search .= " AND $wpdb->posts.post_type IN ('post')";
    $search .= " AND $wpdb->posts.post_status = 'publish'";

    remove_filter('posts_join', 'custom_posts_join' );
    remove_filter('posts_groupby', 'custom_posts_groupby' );        
    return $search;
}
add_filter( 'posts_search', 'custom_search_posts', 500, 2 );

関数 custom_posts_join postmeta上でpostsに参加して著者による投稿を検索することを可能にします。

function custom_posts_join($join){
    global $wpdb;
    if( is_search() && !is_admin()) {
        $join .= " LEFT JOIN $wpdb->postmeta ON $wpdb->posts.ID = $wpdb->postmeta.post_id ";    
    }
    return $join;
}

関数 custom_posts_groupby postmetapostsを投稿ごとにグループ化するID

function custom_posts_groupby( $groupby ) {
    global $wpdb;
    if( is_search() && !is_admin()) {   
        $groupby = "$wpdb->posts.ID";
    }
    return $groupby;
}

私はいくつかのmysqlクエリを介してユーザーを照会するのに苦労したので、代わりにWP_User_Queryを使用しました。

誰かが来て、コードを改良してくれることを願っています。大部分はパフォーマンスの面でです。

編集: この場合posts_joinposts_groupbyは必要ありません。

1
Gixty