web-dev-qa-db-fra.com

WP_Query avec "post_title LIKE 'quelquechose%'"?

J'ai besoin de faire un WP_Query avec un LIKE sur le post_title.

J'ai commencé avec ce WP_Query régulier:

$wp_query = new WP_Query( 
    array (
        'post_type'        => 'wp_exposants',
        'posts_per_page'   => '1',
        'post_status'      => 'publish',
        'orderby'          => 'title', 
        'order'            => 'ASC',
        'paged'            => $paged
    )
); 

Mais ce que je veux réellement faire ressemble à ceci en SQL:

$query = "
        SELECT      *
        FROM        $wpdb->posts
        WHERE       $wpdb->posts.post_title LIKE '$param2%'
        AND         $wpdb->posts.post_type = 'wp_exposants'
        ORDER BY    $wpdb->posts.post_title
";
$wpdb->get_results($query);

La sortie affiche les résultats que j'attends, mais j'utilise la <?php while ( $wp_query->have_posts() ) : $wp_query->the_post(); ?> régulière pour afficher les résultats.
Et cela ne fonctionne pas avec $wpdb->get_results().

Comment puis-je atteindre ce que j'ai décrit ici?

43
Ludo

Je résoudrais ceci avec un filtre sur WP_Query. Celui qui détecte une variable de requête supplémentaire et l’utilise comme préfixe du titre.

add_filter( 'posts_where', 'wpse18703_posts_where', 10, 2 );
function wpse18703_posts_where( $where, &$wp_query )
{
    global $wpdb;
    if ( $wpse18703_title = $wp_query->get( 'wpse18703_title' ) ) {
        $where .= ' AND ' . $wpdb->posts . '.post_title LIKE \'' . esc_sql( $wpdb->esc_like( $wpse18703_title ) ) . '%\'';
    }
    return $where;
}

De cette façon, vous pouvez toujours appeler WP_Query, il vous suffit de passer le titre en tant qu'argument wpse18703_title (ou de changer le nom en un nom plus court).

44
Jan Fabry

Simplifié:

function title_filter( $where, &$wp_query )
{
    global $wpdb;
    if ( $search_term = $wp_query->get( 'search_prod_title' ) ) {
        $where .= ' AND ' . $wpdb->posts . '.post_title LIKE \'%' . esc_sql( like_escape( $search_term ) ) . '%\'';
    }
    return $where;
}

$args = array(
    'post_type' => 'product',
    'posts_per_page' => $page_size,
    'paged' => $page,
    'search_prod_title' => $search_term,
    'post_status' => 'publish',
    'orderby'     => 'title', 
    'order'       => 'ASC'
);

add_filter( 'posts_where', 'title_filter', 10, 2 );
$wp_query = new WP_Query($args);
remove_filter( 'posts_where', 'title_filter', 10, 2 );
return $wp_query;
17
Rao

Je voulais mettre à jour ce code sur lequel vous avez travaillé pour wordpress 4.0 et versions supérieures, car esc_sql () est obsolète dans la version 4.0.

function title_filter($where, &$wp_query){
    global $wpdb;

    if($search_term = $wp_query->get( 'search_prod_title' )){
        /*using the esc_like() in here instead of other esc_sql()*/
        $search_term = $wpdb->esc_like($search_term);
        $search_term = ' \'%' . $search_term . '%\'';
        $where .= ' AND ' . $wpdb->posts . '.post_title LIKE '.$search_term;
    }

    return $where;
}

Le reste est pareil.

De plus, je tiens à préciser que vous pouvez utiliser s variable dans les arguments de WP_Query pour transmettre les termes de recherche, ce qui permettra également de rechercher le titre du message, je crois.

Comme ça:

$args = array(
    'post_type' => 'post',
    's' => $search_term,
    'post_status' => 'publish',
    'orderby'     => 'title', 
    'order'       => 'ASC'        
);
$wp_query = new WP_Query($args);
16
Ashan Jay

Avec une solution vulnérable publiée ici, je viens avec une version un peu simplifiée et assainie.

Tout d'abord, nous créons une fonction pour le filtre posts_where qui vous permet d'afficher uniquement les publications correspondant à des conditions spécifiques:

function cc_post_title_filter($where, &$wp_query) {
    global $wpdb;
    if ( $search_term = $wp_query->get( 'cc_search_post_title' ) ) {
        $where .= ' AND ' . $wpdb->posts . '.post_title LIKE \'%' . $wpdb->esc_like( $search_term ) . '%\'';
    }
    return $where;
}

Maintenant, nous ajoutons cc_search_post_title dans nos arguments de requête:

$args = array(
    'cc_search_post_title' => $search_term, // search post title only
    'post_status' => 'publish',
);

Et enfin, enroulez le filtre autour de la requête:

add_filter( 'posts_where', 'cc_post_title_filter', 10, 2 );
$query = new WP_Query($args);
remove_filter( 'posts_where', 'cc_post_title_filter', 10 );

Utiliser get_posts ()

Certaines fonctions récupérant des publications ne font pas de filtres. Par conséquent, les fonctions de filtre posts_where que vous attachez ne modifieront pas la requête. Si vous envisagez d'utiliser get_posts() pour interroger vos publications, vous devez définir suppress_filters sur false dans votre tableau d'arguments:

$args = array(
    'cc_search_post_title' => $search_term,
    'suppress_filters' => FALSE,
    'post_status' => 'publish',
);

Maintenant, vous pouvez utiliser get_posts():

add_filter( 'posts_where', 'cc_post_title_filter', 10, 2 );
$posts = get_posts($args);
remove_filter( 'posts_where', 'cc_post_title_filter', 10 );

Qu'en est-il du paramètre s?

Le paramètre s est disponible:

$args = array(
    's' => $search_term,
);

Lors de l'ajout du terme de recherche dans le paramètre s, la recherche sera effectuée dans le titre de l'article, le aussi cherchera dans le contenu de l'article.

Qu'en est-il du paramètre title qui a été ajouté avec WP 4.4?

Passer un terme de recherche dans le paramètre title:

$args = array(
    'title' => $search_term,
);

Est sensible à la casse et LIKE, pas %LIKE%. Cette recherche moyenne de hello ne renverra pas de message avec le titre Hello World ou Hello.

9
Christine Cooper

En me basant sur d’autres réponses que j’ai devant moi, pour offrir une certaine souplesse dans la situation où vous souhaitez rechercher un article contenant un mot dans un méta-champ OR dans le titre du message, je donne cette option via l’argument " title_filter_relation. " Dans cette implémentation, je n'autorise que les entrées "OU" ou "ET" avec la valeur par défaut de "ET".

function title_filter($where, &$wp_query){
    global $wpdb;
    if($search_term = $wp_query->get( 'title_filter' )){
        $search_term = $wpdb->esc_like($search_term); //instead of esc_sql()
        $search_term = ' \'%' . $search_term . '%\'';
        $title_filter_relation = (strtoupper($wp_query->get( 'title_filter_relation'))=='OR' ? 'OR' : 'AND');
        $where .= ' '.$title_filter_relation.' ' . $wpdb->posts . '.post_title LIKE '.$search_term;
    }
    return $where;
}

Voici un exemple de code en action pour un type de message très simple "faq" où la question est le titre du message lui-même:

add_filter('posts_where','title_filter',10,2);
$s1 = new WP_Query( array(
    'post_type' => 'faq',
    'posts_per_page' => -1,
    'title_filter' => $q,
    'title_filter_relation' => 'OR',
    'post_status' => 'publish',
    'orderby'     => 'title', 
    'order'       => 'ASC',
    'meta_query' => array(
        'relation' => 'OR',
        array(
            'key' => 'faq_answer',
            'value' => $q,
            'compare' => 'LIKE'
        )
    )
));
remove_filter('posts_where','title_filter',10,2);
7
David Choy