Come includere i dati di wp_postmeta nella ricerca?
Ho un sito che utilizza Advanced Custom Fields per creare e memorizzare varie informazioni rilevanti. Queste devono essere incluse nella ricerca generale principale, che di default cerca solo nel titolo e nel contenuto principale.
Ho trovato molte informazioni su come ottenere risultati di ricerca basati su specifici elementi di postmeta, ma ho un problema con questo. Ci sono potenzialmente un numero illimitato di campi in postmeta da cercare.
La soluzione potrebbe essere quella di cercare qualsiasi cosa in postmeta o qualsiasi cosa con un meta_key che corrisponda a questa espressione regolare: content_section_[0-9]{1,4}_content_.{2,8}
Esempi di meta_keys da trovare sono:
content_section_0_content_title
content_section_0_content_title
content_section_4_content_subtitle
content_section_8_content_text
Qualsiasi modo per modificare i campi di ricerca per includere il postmeta sarebbe molto apprezzato.
Aggiungi questo al tuo plugin o al file functions.php del tuo tema. L'esempio qui sotto includerà 'your_key' nella ricerca. Puoi includere tutte le tue chiavi ripetendo l'array.
function me_search_query( $query ) {
if ( $query->is_search ) {
$meta_query_args = array(
array(
'key' => 'your_key',
'value' => $query->query_vars['s'] = '',
'compare' => 'LIKE',
),
);
$query->set('meta_query', $meta_query_args);
};
}
add_filter( 'pre_get_posts', 'me_search_query');

Questo corrisponderà solo ai post che corrispondono al termine di ricerca nel titolo/contenuto e nel campo meta, il che non è come funziona tipicamente una ricerca full text.

Questa funzione dovrebbe funzionare, anche dopo l'aggiornamento di sicurezza di WP 4.8.3.
Utilizzo:
// Aggiungi questo nel file functions.php
add_meta_field_to_search_query('right_data');
add_meta_field_to_search_query('extra_search_terms');
Implementazione:
/* AGGIUNGI CAMPO META ALLA RICERCA */
function add_meta_field_to_search_query($field){
if(isset($GLOBALS['added_meta_field_to_search_query'])){
$GLOBALS['added_meta_field_to_search_query'][] = '\'' . $field . '\'';
return;
}
$GLOBALS['added_meta_field_to_search_query'] = array();
$GLOBALS['added_meta_field_to_search_query'][] = '\'' . $field . '\'';
add_filter('posts_join', function($join){
global $wpdb;
if (is_search()){
$join .= " LEFT JOIN $wpdb->postmeta ON $wpdb->posts.ID = $wpdb->postmeta.post_id ";
}
return $join;
});
add_filter('posts_groupby', function($groupby){
global $wpdb;
if (is_search()) {
$groupby = "$wpdb->posts.ID";
}
return $groupby;
});
add_filter('posts_search', function($search_sql){
global $wpdb;
$search_terms = get_query_var('search_terms');
if(!empty($search_terms)){
foreach ($search_terms as $search_term){
$old_or = "OR ({$wpdb->posts}.post_content LIKE '{$wpdb->placeholder_escape()}{$search_term}{$wpdb->placeholder_escape()}')";
$new_or = $old_or . " OR ({$wpdb->postmeta}.meta_value LIKE '{$wpdb->placeholder_escape()}{$search_term}{$wpdb->placeholder_escape()}' AND {$wpdb->postmeta}.meta_key IN (" . implode(', ', $GLOBALS['added_meta_field_to_search_query']) . "))";
$search_sql = str_replace($old_or, $new_or, $search_sql);
}
}
$search_sql = str_replace( " ORDER BY ", " GROUP BY $wpdb->posts.ID ORDER BY ", $search_sql );
return $search_sql;
});
}
Diverse persone hanno implementato questo in modi diversi:
http://websmartdesign.nz/searching-structured-post-data-with-wordpress/ https://adambalee.com/search-wordpress-by-custom-fields-without-a-plugin/

Il link per adambalee.com
ha funzionato per me. Esegue semplicemente una ricerca generale in tutti i meta dei post.

Allo stesso modo, la soluzione linkata su https://adambalee.com/search-wordpress-by-custom-fields-without-a-plugin/ ha funzionato per me su WordPress 5.1.1...

Questa è una versione migliorata della risposta di Ahmed:
function me_search_query( $query ) {
if ( $query->is_search ) {
$meta_query_args = array(
array(
'key' => 'your_key',
'value' => $query->query_vars['s'],
'compare' => 'LIKE',
),
);
$query->set('meta_query', $meta_query_args);
add_filter( 'get_meta_sql', 'me_replace_and_with_or' );
};
}
function me_replace_and_with_or( $sql ) {
if ( 1 === strpos( $sql['where'], 'AND' ) ) {
$sql['where'] = substr( $sql['where'], 4 );
$sql['where'] = ' OR ' . $sql['where'];
}
//assicurati che questo filtro venga eseguito solo una volta per la meta query
remove_filter( 'get_meta_sql', 'me_replace_and_with_or' );
return $sql;
}
add_filter( 'pre_get_posts', 'me_search_query');
Il problema è che WordPress genera la meta query con l'operatore "AND", e mostrerebbe solo i post che hanno la stringa di ricerca in entrambi i luoghi - titolo E meta, oppure contenuto E meta. Quindi, abbiamo bisogno di creare un filtro aggiuntivo per cambiare "AND" in "OR" (e poi rimuovere quel filtro per non rompere nient'altro).

Cambiare l'AND in OR interrompe la logica SQL per filtrare il tipo di POST, quindi la ricerca verrà applicata a tutti i tipi di post, inclusi gli allegati. Sto ancora cercando di trovare una soluzione valida che funzioni con la combinazione di ricerca e filtri su un CPT

Se vuoi utilizzare un plugin, Relevanssi - Una ricerca migliore potrebbe valere la pena provare.
La versione standard (gratuita) supporta la ricerca nei metadati dei post.

Questa è la soluzione più semplice e attualmente funzionante. Nessuna delle precedenti ha funzionato per me. È testata e funzionante con Wordpress 5.3.1.
Inserisci il seguente codice nel tuo file functions.php per agganciarti al filtro posts_clauses
.
/**
* Includi i campi meta nella ricerca
*
* @author Mindaugas // meevly.com
* @link https://meevly.com/services/custom-wordpress-themes-and-plugins/
*
* @param array $pieces pezzi della query.
* @param WP_Query $args oggetto della query.
* @return array
*/
function mv_meta_in_search_query( $pieces, $args ) {
global $wpdb;
if ( ! empty( $args->query['s'] ) ) { // esegui solo su query di ricerca.
$keywords = explode(' ', get_query_var('s'));
$escaped_percent = $wpdb->placeholder_escape(); // WordPress scappa il carattere "%" dalla versione 4.8.3, quindi non possiamo usare direttamente il carattere percentuale.
$query = "";
foreach ($keywords as $word) {
$query .= " (unique_postmeta_selector.meta_value LIKE '{$escaped_percent}{$word}{$escaped_percent}') OR ";
}
if ( ! empty( $query ) ) { // aggiungi le clausole WHERE e JOIN necessarie.
$pieces['where'] = str_replace( "((({$wpdb->posts}.post_title LIKE '{$escaped_percent}", "( {$query} (({$wpdb->posts}.post_title LIKE '{$escaped_percent}", $pieces['where'] );
$pieces['join'] = $pieces['join'] . " INNER JOIN {$wpdb->postmeta} AS unique_postmeta_selector ON ({$wpdb->posts}.ID = unique_postmeta_selector.post_id) ";
}
}
return $pieces;
}
add_filter( 'posts_clauses', 'mv_meta_in_search_query', 20, 2 );
E la tua query dovrebbe essere simile alla seguente. Nota che suppress_filters => false
è obbligatorio! Non funzionerà senza di esso.
$search_posts_array = array(
'suppress_filters' => false,
's' => $keyword,
);
$search_results = get_posts( $search_posts_array );

Non sono sicuro, ma per ottenere tutte le chiavi/valori dei campi personalizzati per la ricerca predefinita sarebbe necessaria una chiamata al database utilizzando wpdb.
L'alternativa ai plugin menzionati da goto10 è una soluzione molto più semplice. Search Everything, WP Custom Fields Search
