WP Query pentru postări care încep cu o anumită literă
Doresc să caut postări cu WP_Query() și să selectez doar postările care încep cu o anumită literă. Am găsit mai multe postări vechi cu filtre care erau dinainte de versiunea 4.4, dar de la 4.4 a fost adăugată o funcționalitate de căutare după titlu în funcția WP_Query.
$q = new WP_Query(array('post_type'=>'post', 'title'=>'Acest Titlu'));
Aceasta va returna doar potriviri exacte ale postărilor cu titlul "Acest Titlu".
Ceea ce aș dori să fac este să returnez toate postările care încep cu, în acest exemplu, litera 'A'.
Am găsit și acest post, care nu a primit niciodată un răspuns satisfăcător. Este marcat ca răspuns acceptat, dar nu văd cum răspunde la întrebare. Cum să limitezi căutarea la prima literă din titlu?
Alte funcționalități de query precum căutările după comentarii sau meta au un parametru 'compare' pentru a adăuga LIKE% în interogări, dar titlul nu pare să aibă această opțiune.

Nu este posibil direct cu WP_Query
în mod implicit, dar prin utilizarea filtrului posts_where
pentru a căuta un argument personalizat pe WP_Query
, este posibil să adăugați această funcționalitate.
Presupunând că starts_with
este numele argumentului pe care dorim să-l folosim, putem filtra posts_where
pentru a adăuga o clauză WHERE
care limitează rezultatele la cele care încep cu valoarea dată dacă starts_with
a fost setat în interogare:
function wpse_298888_posts_where( $where, $query ) {
global $wpdb;
$starts_with = esc_sql( $query->get( 'starts_with' ) );
if ( $starts_with ) {
$where .= " AND $wpdb->posts.post_title LIKE '$starts_with%'";
}
return $where;
}
add_filter( 'posts_where', 'wpse_298888_posts_where', 10, 2 );
Cu acest filtru adăugat, putem interoga postări astfel:
$query = new WP_Query( array(
'starts_with' => 'M',
) );
Aceasta va returna toate postările care încep cu "M".
Dacă doriți să puteți filtra interogarea principală, puteți folosi acest argument și în pre_get_posts
:
function wpse_298888_pre_get_posts( $query ) {
if ( $query->is_main_query() ) {
$query->set( 'starts_with', 'M' );
}
}
add_action( 'pre_get_posts', 'wpse_298888_pre_get_posts' );

Acest lucru funcționează perfect, dar am făcut o ajustare care ar putea ajuta și pe alții. Am folosit REGEXP în loc de LIKE pentru a putea grupa într-o singură categorie titlurile care încep cu cifre din intervalul 0-9.
$where .= " AND $wpdb->posts.post_title REGEXP '^$starts_with'";

Ar fi posibil să facem asta invers, unde ai putea selecta toate articolele și/sau paginile care nu încep cu o anumită literă/șir de caractere? Vreau să exclud din rezultatele căutării anumite pagini al căror titlu începe cu același cuvânt, dar vreau să păstrez opțiunea deschisă în cazul în care vor fi create mai multe astfel de pagini, în loc să folosesc ID-uri statice. Acestea nu sunt articole, deci nu au etichete sau categorii.

Pur și simplu schimbați LIKE
din primul bloc de cod în NOT LIKE
.

Se pare că acest lucru nu funcționează. Primește o 'eroare critică' în WordPress.

Am verificat din nou și nu văd nicio problemă în cod. Dacă nu ai copiat exact acest cod, probabil ai o eroare de sintaxă în codul tău undeva.

@VincenzoPiromalli Dacă filtrezi interogarea principală cu metoda pre_get_posts
, atunci orice paginare normală va funcționa.

Doar să fii conștient că dacă ai titluri într-o limbă complicată cu diacritice, rezultatul poate să nu fie precis. Colația bazei de date a câmpului de titlu joacă un rol important. Chiar și atunci rezultatul poate să nu fie perfect. În plus, aș evita șirul de caractere pe care îl introduci cu ceva de genul: mb_substr($starts_with, 0, 1) // pentru CH și litere duble și într-adevăr $wpdb->esc_like()
