Extinderea contextului de căutare în ecranul listei de postări din admin
Am creat un tip de postare personalizat și i-am atașat câteva câmpuri personalizate. Acum aș dori ca funcția de căutare pe care autorii o pot efectua în ecranul listei de postări personalizate (în panoul de administrare) să fie executată și pe câmpurile meta și nu doar să caute în titlu și conținut ca de obicei.
Unde pot să mă conectez și ce cod trebuie să folosesc?
Imagine exemplu
Stefano

Am rezolvat filtrarea interogării prin adăugarea unei alături pe tabelul postmeta și modificarea clauzei WHERE. Sfaturi despre filtrarea clauzei WHERE (adesea necesită căutare și înlocuire cu expresii regulate) sunt aici pe codex:
add_filter( 'posts_join', 'segnalazioni_search_join' );
function segnalazioni_search_join ( $join ) {
global $pagenow, $wpdb;
// Vreau ca filtrul să se aplice doar când se efectuează o căutare pe pagina de editare a Tipului de Postare Personalizat numit "segnalazioni".
if ( is_admin() && 'edit.php' === $pagenow && 'segnalazioni' === $_GET['post_type'] && ! empty( $_GET['s'] ) ) {
$join .= 'LEFT JOIN ' . $wpdb->postmeta . ' ON ' . $wpdb->posts . '.ID = ' . $wpdb->postmeta . '.post_id ';
}
return $join;
}
add_filter( 'posts_where', 'segnalazioni_search_where' );
function segnalazioni_search_where( $where ) {
global $pagenow, $wpdb;
// Vreau ca filtrul să se aplice doar când se efectuează o căutare pe pagina de editare a Tipului de Postare Personalizat numit "segnalazioni".
if ( is_admin() && 'edit.php' === $pagenow && 'segnalazioni' === $_GET['post_type'] && ! empty( $_GET['s'] ) ) {
$where = preg_replace(
"/\(\s*" . $wpdb->posts . ".post_title\s+LIKE\s*(\'[^\']+\')\s*\)/",
"(" . $wpdb->posts . ".post_title LIKE $1) OR (" . $wpdb->postmeta . ".meta_value LIKE $1)", $where );
$where.= " GROUP BY {$wpdb->posts}.id"; // Rezolvă rezultatele duplicate
}
return $where;
}

Uau! Exact ce căutam. Totuși, cred că am găsit un bug - când caut după titlul articolului, primesc un rezultat care apoi este duplicat de 5 ori în rezultate!?! http://imgur.com/eE52gIA

Iată un alt screenshot cu SQL-ul afișat: http://tinypic.com/view.php?pic=124tqb6&s=5 Nu înțeleg de ce primesc 5 rezultate!?!

Am postat o întrebare separată despre repararea bug-ului cu duplicatele: http://wordpress.stackexchange.com/questions/111185/how-do-i-improve-this-admin-query-snippet-to-avoid-generating-duplicate-results

Acest post și cel de mai jos mi-au fost utile. Acum trebuie să găsesc o modalitate de a include căutarea după autorul postării și de a afișa postările realizate de acesta.

@Stefano, rezultatele căutării funcționează. Am o problemă, câmpul implicit „Titlul postării” afișează în mod repetat același rezultat în partea de administrare. Vezi:https://imgur.com/a/W4wmXhO

Răspunsul lui Stefano este foarte bun, dar îi lipsește o clauză distinctă:
function segnalazioni_search_distinct( $where ){
global $pagenow, $wpdb;
if ( is_admin() && $pagenow=='edit.php' && $_GET['post_type']=='segnalazioni' && $_GET['s'] != '') {
return "DISTINCT";
}
return $where;
}
add_filter( 'posts_distinct', 'segnalazioni_search_distinct' );
Adaugă codul de mai sus, actualizează-l și va funcționa fără duplicate.

Acest lucru va funcționa,
function custom_search_query( $query ) {
$custom_fields = array(
// aici se introduc toate câmpurile meta în care doriți să căutați
"rg_first_name",
"rg_1job_designation"
);
$searchterm = $query->query_vars['s'];
// trebuie să eliminăm parametrul "s" din interogare, deoarece va împiedica găsirea postărilor
$query->query_vars['s'] = "";
if ($searchterm != "") {
$meta_query = array('relation' => 'OR');
foreach($custom_fields as $cf) {
array_push($meta_query, array(
'key' => $cf,
'value' => $searchterm,
'compare' => 'LIKE'
));
}
$query->set("meta_query", $meta_query);
};
}
add_filter( "pre_get_posts", "custom_search_query");

Te rog să indentăm codul corect și să incluzi o explicație despre de ce și cum acest lucru va funcționa.

Deși inițial am dat un vot pozitiv, am realizat că, din păcate, acest lucru va funcționa la fel pentru fiecare căutare și ar putea afecta căutarea pe partea de front-end.

Adăugarea unei verificări if ( $query->query['post_type'] != 'your_custom_post_type' ){ return; }
la începutul funcției va împiedica rularea acesteia pe alte căutări. Reține că tehnica din acest răspuns nu mai caută în post_title, iar readăugarea acestei funcționalități nu este trivială.

Încă o problemă - Indicatorul Rezultatele căutării pentru „<cuvânt cheie>” apelează get_search_query()
care la rândul său apelează get_query_var( 's' )
. Deoarece "s" este setat la șir gol, Rezultatele căutării pentru „” va avea întotdeauna o valoare goală între ghilimele. Există vreo modificare la această soluție care să rezolve această problemă?

O altă problemă, această soluție va funcționa doar pentru valorile meta acum. Căutările după titlu, de exemplu, nu vor funcționa.

Soluția 1: Adăugați acest cod în fișierul de funcții și modificați/adăugați mai multe nume de coloane pe care le-ați folosit în tipul de postare personalizat
function extend_admin_search( $query ) {
// folosiți tipul vostru de postare
$post_type = 'document';
// Folosiți câmpurile/coloanele personalizate pentru căutare
$custom_fields = array(
"_file_name",
);
if( ! is_admin() )
return;
if ( $query->query['post_type'] != $post_type )
return;
$search_term = $query->query_vars['s'];
// Setați la gol, altfel nu va găsi nimic
$query->query_vars['s'] = '';
if ( $search_term != '' ) {
$meta_query = array( 'relation' => 'OR' );
foreach( $custom_fields as $custom_field ) {
array_push( $meta_query, array(
'key' => $custom_field,
'value' => $search_term,
'compare' => 'LIKE'
));
}
$query->set( 'meta_query', $meta_query );
};
}
add_action( 'pre_get_posts', 'extend_admin_search' );
Soluția 2: (Recomandat) Folosiți acest cod în fișierul de funcții fără nicio modificare
function cf_search_join( $join ) {
global $wpdb;
if ( is_search() ) {
$join .=' LEFT JOIN '.$wpdb->postmeta. ' ON '. $wpdb->posts . '.ID = ' . $wpdb->postmeta . '.post_id ';
}
return $join;
}
add_filter('posts_join', 'cf_search_join' );
function cf_search_where( $where ) {
global $pagenow, $wpdb;
if ( is_search() ) {
$where = preg_replace(
"/\(\s*".$wpdb->posts.".post_title\s+LIKE\s*(\'[^\']+\')\s*\)/",
"(".$wpdb->posts.".post_title LIKE $1) OR (".$wpdb->postmeta.".meta_value LIKE $1)", $where );
}
return $where;
}
add_filter( 'posts_where', 'cf_search_where' );
function cf_search_distinct( $where ) {
global $wpdb;
if ( is_search() ) {
return "DISTINCT";
}
return $where;
}
add_filter( 'posts_distinct', 'cf_search_distinct' );

Cu acest cod poți căuta în lista de articole din Panoul de Administrare WordPress folosind valorile meta personalizate ale postărilor, împreună cu titlul și alte câmpuri implicite.
Te rugăm să adaugi codul de mai jos în fișierul functions.php:
if (!function_exists('extend_admin_search')) {
add_action('admin_init', 'extend_admin_search');
/**
* conectează căutarea postărilor dacă suntem pe pagina de administrare pentru tipul nostru
*/
function extend_admin_search() {
global $typenow;
if ($typenow === 'your_custom_post_type') {
add_filter('posts_search', 'posts_search_custom_post_type', 10, 2);
}
}
/**
* adaugă condiție de interogare pentru meta personalizate
* @param string $search șirul de căutare până acum
* @param WP_Query $query
* @return string
*/
function posts_search_custom_post_type($search, $query) {
global $wpdb;
if ($query->is_main_query() && !empty($query->query['s'])) {
$sql = "
or exists (
select * from {$wpdb->postmeta} where post_id={$wpdb->posts}.ID
and meta_key in ('custom_field1','custom_field2')
and meta_value like %s
)
";
$like = '%' . $wpdb->esc_like($query->query['s']) . '%';
$search = preg_replace("#\({$wpdb->posts}.post_title LIKE [^)]+\)\K#",
$wpdb->prepare($sql, $like), $search);
}
return $search;
}
}

Te rog să nu copiezi răspunsul tău la fiecare întrebare similară. Odată ce vei avea reputație suficientă, vei putea comenta pe orice postare și să oferi un link către răspunsul tău.

Versiunea codului prezentată în câteva răspunsuri, care modifică parametrul meta_query al WP_Query în pre_get_posts, nu mai căuta în post_title. Adăugarea capacității de a căuta fie în titlul postării, fie în valorile meta, nu poate fi realizată direct în WP_Query fără modificarea SQL, din păcate, așa cum este explicat în această întrebare: Utilizarea meta query ('meta_query') cu un query de căutare ('s')
Am combinat câteva dintre tehnicile prezentate pentru a obține o versiune funcțională care evită preg_replaces și prea multe modificări SQL (aș fi dorit să le evit complet). Singurul dezavantaj este că după o căutare, textul subtitlului din partea de sus a paginii afișează "Rezultatele căutării pentru ''". Am ascuns acest text cu CSS pentru tipul meu personalizat de post.
/**
* Extinde căutarea pentru tipul personalizat de post pentru a căuta și în câmpurile meta
* @param WP_Query $query
*/
function extend_cpt_admin_search( $query ) {
// Asigură-te că suntem în zona de administrare și că acesta este tipul nostru personalizat de post
if ( !is_admin() || $query->query['post_type'] != 'your_custom_post_type' ){
return;
}
// Adaugă aici toate câmpurile meta pe care dorești să le incluzi în căutare
$custom_fields = array(
"your_custom_meta_field",
"your_custom_meta_field2",
"your_custom_meta_field3"
);
// Șirul de caractere introdus prin formularul de căutare
$searchterm = $query->query_vars['s'];
// Setează la gol, altfel nu vor fi returnate rezultate.
// Singurul dezavantaj este că textul afișat al căutării este gol în partea de sus a paginii.
$query->query_vars['s'] = '';
if ($searchterm != ""){
// Adaugă parametrul meta_query suplimentar la obiectul WP_Query.
// Referință: https://codex.wordpress.org/Class_Reference/WP_Query#Custom_Field_Parameters
$meta_query = array();
foreach($custom_fields as $cf) {
array_push($meta_query, array(
'key' => $cf,
'value' => $searchterm,
'compare' => 'LIKE'
));
}
// Utilizează o comparație 'OR' pentru fiecare câmp meta personalizat suplimentar.
if (count($meta_query) > 1){
$meta_query['relation'] = 'OR';
}
// Setează parametrul meta_query
$query->set('meta_query', $meta_query);
// Pentru a permite căutării să returneze și rezultate "OR" pe post_title
$query->set('_meta_or_title', $searchterm);
}
}
add_action('pre_get_posts', 'extend_cpt_admin_search');
