web-dev-qa-db-fra.com

Comment rechercher des articles IN OR Titre OR contenu OR auteur?

J'ai consulté de nombreux articles et questions concernant la recherche de méta personnalisée, mais je souhaite rechercher des articles et les inclure si la requête de recherche correspond à un nom d'auteur.

Je suis venu avec le code suivant mais cela ne fonctionne pas. Pour une raison quelconque, il renvoie les publications ayant le statut "révision"

Tout d'abord, j'ai accroché mes trois fonctions à leurs crochets respectifs:

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

Ensuite, je procède à chaque fonction:

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

Après un travail acharné et des recherches, j'ai finalement trouvé cette solution de travail.

N'hésitez pas à améliorer ce code et à poster une réponse alternative. Pour une raison quelconque, la requête semble être exécutée plus d'une fois (trois à quatre fois dans mon cas).

Ici, je me sers de trois crochets, posts_search, posts_join et posts_groupby

Fonction custom_search_posts vous permet de rechercher des termes et des utilisateurs ensemble.

-Rechercher des utilisateurs et des termes. Par exemple: S'il existe un article intitulé Money écrit par l'utilisateur Smith . Vous pouvez rechercher Smith money et le résultat sera annoncé après. NOTE: le nom de l'auteur doit venir avant le terme.

-Rechercher uniquement les utilisateurs (usermeta, first_name OR last_name)

-Rechercher uniquement les termes (dans les titres uniquement).

-Vous pouvez même rechercher plusieurs utilisateurs à la fois.

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 );

La fonction custom_posts_join nous permet de rejoindre postmeta sur posts pour rechercher des publications par auteur.

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;
}

Fonction custom_posts_groupby maintenant nous groupons postmeta et posts par posts ID

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

J'ai eu quelques problèmes pour interroger les utilisateurs via des requêtes mysql, j'ai donc utilisé WP_User_Query à la place.

J'espère que quelqu'un viendra améliorer le code, principalement en termes de performances.

EDIT: Il n'est pas nécessaire d'utiliser posts_join et posts_groupby dans ce cas.

1
Gixty