Cum să incluzi date din wp_postmeta în căutare?
Am un site care folosește Advanced Custom Fields pentru a crea și stoca diverse informații relevante. Acestea trebuie incluse în căutarea generală principală, care în mod implicit caută doar în titlu și conținutul principal.
Am găsit multe informații despre obținerea rezultatelor căutării bazate pe anumite părți din postmeta, dar am o problemă cu asta. Există un număr potențial nelimitat de câmpuri în postmeta care trebuie căutate.
Soluția ar putea fie să caute orice în postmeta, fie să caute orice cu un meta_key care se potrivește cu această expresie regulată: content_section_[0-9]{1,4}_content_.{2,8}
Exemple de meta_keys care trebuie să se potrivească sunt:
content_section_0_content_title
content_section_0_content_title
content_section_4_content_subtitle
content_section_8_content_text
Orice modalitate prin care pot modifica câmpurile căutate pentru a include postmeta ar fi foarte apreciată.
Adăugați acest cod în plugin-ul dvs. sau în fișierul functions.php al temei. Exemplul de mai jos va include 'your_key' în căutare. Puteți include toate cheile dorite prin repetarea array-ului.
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');

Acesta va potrivi doar articolele care corespund termenului de căutare în titlu/conținut și în câmpul meta, ceea ce nu este modul în care funcționează de obicei o căutare full-text.

Această funcție ar trebui să funcționeze, chiar și după actualizarea de securitate WP 4.8.3.
Utilizare:
// Adăugați acest cod în functions.php
add_meta_field_to_search_query('right_data');
add_meta_field_to_search_query('extra_search_terms');
Implementare:
/* ADĂUGĂ CÂMP META ÎN INTEROGAREA DE CĂUTARE */
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;
});
}
Mai multe persoane au implementat această funcționalitate în moduri diferite:
http://websmartdesign.nz/searching-structured-post-data-with-wordpress/ https://adambalee.com/search-wordpress-by-custom-fields-without-a-plugin/

Link-ul pentru adambalee.com
a funcționat pentru mine. Face doar o căutare generală în toate metadatele postărilor.

La fel, soluția prezentată la https://adambalee.com/search-wordpress-by-custom-fields-without-a-plugin/ a funcționat pentru mine pe WordPress 5.1.1...

Acesta este un răspuns îmbunătățit al lui 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'];
}
//asigură-te că acest filtru se va declanșa doar o singură dată pentru interogarea meta
remove_filter( 'get_meta_sql', 'me_replace_and_with_or' );
return $sql;
}
add_filter( 'pre_get_posts', 'me_search_query');
Problema este că WordPress generează interogări meta cu operatorul "AND", ceea ce ar afișa doar postările care conțin șirul de căutare în ambele locuri - titlu ȘI meta, sau conținut ȘI meta. Prin urmare, trebuie să creăm un filtru suplimentar pentru a schimba "AND" în "OR" (și apoi să eliminăm acel filtru pentru a nu afecta altceva).

Schimbarea operatorului AND în OR distruge logica SQL pentru filtrarea tipului POST, astfel încât căutarea se va aplica pe toate tipurile de postări, inclusiv fișierele atașate. Încă încerc să găsesc o soluție viabilă care să funcționeze atât cu căutarea, cât și cu filtrele combinate pe un CPT (Custom Post Type).

Dacă ești dispus să folosești un plugin, Relevanssi - O Căutare Mai Bună ar putea fi o opțiune de încercat.
Versiunea standard (gratuită) suportă căutarea în meta-datelor articolelor.

Acesta este cea mai simplă și funcțională soluție în prezent. Niciuna dintre cele menționate mai sus nu a funcționat pentru mine. Este testat și funcționează cu WordPress 5.3.1.
Introduceți următorul cod în fișierul functions.php pentru a-l conecta la filtrul posts_clauses
.
/**
* Include meta fields in search
*
* @author Mindaugas // meevly.com
* @link https://meevly.com/services/custom-wordpress-themes-and-plugins/
*
* @param array $pieces componentele interogării.
* @param WP_Query $args obiectul interogării.
* @return array
*/
function mv_meta_in_search_query( $pieces, $args ) {
global $wpdb;
if ( ! empty( $args->query['s'] ) ) { // rulează doar la interogarea de căutare.
$keywords = explode(' ', get_query_var('s'));
$escaped_percent = $wpdb->placeholder_escape(); // WordPress scapează "%" începând cu versiunea 4.8.3, așa că nu putem folosi caracterul procent direct.
$query = "";
foreach ($keywords as $word) {
$query .= " (unique_postmeta_selector.meta_value LIKE '{$escaped_percent}{$word}{$escaped_percent}') OR ";
}
if ( ! empty( $query ) ) { // adaugă condițiile WHERE și JOIN necesare.
$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 );
Și interogarea ar trebui să arate astfel. Vă rugăm să rețineți că suppress_filters => false
este obligatoriu! Nu va funcționa fără el.
$search_posts_array = array(
'suppress_filters' => false,
's' => $keyword,
);
$search_results = get_posts( $search_posts_array );

Nu sunt sigur, dar pentru a prelua toate cheile/valorile câmpurilor personalizate pentru căutarea implicită ar fi necesară o interogare la baza de date folosind wpdb.
Alternativa la plugin-urile menționate de goto10 reprezintă o soluție mult mai simplă. Search Everything, WP Custom Fields Search
