WP_Query con "post_title COME" qualcosa% ""?


44

Ho bisogno di fare un WP_Querycon un LIKEsu post_title.

Ho iniziato con questo normale WP_Query:

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

Ma quello che voglio davvero fare è simile a questo in 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);

L'output stampa i risultati che mi aspetto, ma uso il normale <?php while ( $wp_query->have_posts() ) : $wp_query->the_post(); ?>per visualizzare i risultati.
E questo non funziona $wpdb->get_results().

Come posso ottenere ciò che ho descritto qui?

Risposte:


45

Lo risolverei con un filtro attivo WP_Query. Uno che rileva una variabile di query aggiuntiva e la utilizza come prefisso del titolo.

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

In questo modo puoi ancora chiamare WP_Query, basta passare il titolo come wpse18703_titleargomento (o cambiare il nome in qualcosa di più breve).


Questo in qualche modo manca il $wpdb->prepare().
Kaiser

@kaiser: è passato molto tempo, ma penso che non sia stato possibile con prepare(). $wpdb->prepare('LIKE "%s%%"', 'banana')ritornerebbe "LIKE ''banana'%'", quindi dobbiamo costruire noi stessi la query e fare anche la fuga.
Jan Fabry,

1
@JanFabry Felice di vederti agaaaaaaaain! :) Passa in chat un po 'di tempo, hm? StopPress sarebbe felice di vederti. A tale proposito prepare(). Sì, è difficile e ho dovuto provarlo più volte, prima di aggirare il problema. Da qualcosa che ho appena fatto: $wpdb->prepare( ' AND {$wpdb->posts}.post_title LIKE %s ', esc_sql( '%'.like_escape( trim( $term ) ).'%' ) ). E sono abbastanza sicuro che esc_sql()non sia necessario e paranoico.
Kaiser

Sembra che non puoi cercare una stringa con '(apostrofo) all'interno. Immagino sia per via della fuga? Non ho ancora trovato la soluzione
Vincent Decaux il

19

semplificata:

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;

13
Includi una spiegazione insieme al tuo codice.
s_ha_dum,

2
Grande semplificazione
Timo Huovinen,

1
Il codice è, credo, spiegato da me, almeno per me. Grazie per aver condiviso lo script completo.
Hassan Dad Khan,

Usa '$ wpdb-> esc_like (' invece di 'esc_sql (like_escape ('
fdrv

@fdrv Hai ragione ma secondo i documenti di wp $ wpdb-> esc_like hai ancora bisogno di esc_sql (). Quindi penso che il codice corretto sarebbe esc_sql ($ wpdb-> esc_like ($ search_term))
Waqas Bukhary,

16

Volevo aggiornare questo codice su cui avete lavorato per wordpress 4.0 e versioni successive poiché esc_sql () è deprecato in 4.0 in poi.

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

Il resto delle cose è lo stesso.

Voglio anche sottolineare che è possibile utilizzare la variabile s negli argomenti WP_Query per passare i termini di ricerca, che cercherò anche il titolo del post.

Come questo:

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

Che cosa search_prod_titleè esattamente ? Dovrei cambiarlo in qualcos'altro?
Antonios Tsimourtos,

Da quando è esc_sqldeprecato? Non è. $wpdb->escapeè però ... developer.wordpress.org/reference/functions/esc_sql
Jeremy

Si noti che il parametro s cerca anche il contenuto del post, che potrebbe non essere l'obiettivo desiderato. =)
Christine Cooper

10

Con alcune soluzioni vulnerabili pubblicate qui, vengo con una versione un po 'semplificata e igienizzata.

Innanzitutto, creiamo una funzione per il posts_wherefiltro che ti consente di mostrare solo i post che soddisfano condizioni specifiche:

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

Ora aggiungiamo cc_search_post_titlenei nostri argomenti di query:

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

E infine avvolgi il filtro attorno alla query:

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

Utilizzo di get_posts ()

Alcune funzioni che recuperano i post non eseguono filtri, quindi le funzioni del filtro posts_where che allevi non modificheranno la query. Se prevedi di utilizzare get_posts()per eseguire query sui tuoi post, devi impostare suppress_filterssu false nell'array degli argomenti:

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

Ora puoi usare 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 );

E il sparametro?

Il sparametro è disponibile:

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

Mentre aggiungi il termine di ricerca nel sparametro di lavoro e cercherà il titolo del post, cercherà anche il contenuto del post.

Che dire del titleparametro che è stato aggiunto con WP 4.4?

Passando un termine di ricerca nel titleparametro:

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

Fa distinzione tra maiuscole e minuscole e LIKEno %LIKE%. Ciò significa che la ricerca di hellonon restituirà il post con titolo Hello Worldo Hello.


Eccellente. Stavo cercando "post_title" come parametro e, ovviamente, non ho trovato nulla.
MastaBaba,

7

Basandomi su altre risposte prima di me, per fornire flessibilità nella situazione in cui si desidera cercare un post che contiene una parola in un meta campo OPPURE nel titolo del post, offro tale opzione tramite l'argomento "title_filter_relation". In questa implementazione, consento solo input "OR" o "AND" con un valore predefinito di "AND".

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

Ecco un esempio del codice in azione per un tipo di post molto semplice "faq" in cui la domanda è il titolo del post stesso:

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

1
Buona conoscenza, aggiunta di "query vars" personalizzate agli argomenti di query passati per WP_Querypoter accedere ad essi all'interno del posts_wherefiltro.
Tom Auger
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.