web-dev-qa-db-fra.com

Comment faire en sorte que la recherche inclut les données de wp_postmeta?

J'ai un site utilisant Advanced Custom Fields pour créer et stocker diverses informations pertinentes. Ceux-ci doivent être inclus dans la recherche générale principale, qui recherche par défaut uniquement le titre et le contenu principal.

J'ai trouvé de nombreuses informations sur l'obtention de résultats de recherche basés sur des éléments spécifiques de postmeta, mais cela me pose problème. La quantité de champs potentiels à rechercher dans Postmeta est potentiellement illimitée.

La solution peut rechercher n'importe quoi dans postmeta ou n'importe quoi avec une meta_key qui correspond à cette expression rationnelle: content_section_[0-9]{1,4}_content_.{2,8}

Les exemples de meta_keys à rechercher sont:

content_section_0_content_title
content_section_0_content_title
content_section_4_content_subtitle
content_section_8_content_text

Toute façon de modifier les champs recherchés pour inclure le postmeta serait très appréciée.

6
Jodi Warren

Si vous êtes prêt à utiliser un plugin, Relevanssi - Une meilleure recherche pourrait valoir la peine d’être essayé.

La version standard (gratuite) prend en charge la recherche après méta.

2
Dave Romsey

Ajoutez ceci à votre fichier plugin ou functions.php de votre thème. L'exemple ci-dessous inclura "your_key" dans la recherche. Vous pouvez inclure toutes vos clés en répétant le tableau.

 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 ('méta_query', $ meta_query_args); 
}; 
} 
 add_filter ('pre_get_posts ',' me_search_query '); 
10
Ahmed

Cette fonction devrait fonctionner même après la mise à jour de sécurité WP 4.8.3.

Usage:

// Do this in functions.php

add_meta_field_to_search_query('right_data');
add_meta_field_to_search_query('extra_search_terms');

La mise en oeuvre:

/* ADD META FIELD TO SEARCH QUERY */

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

Plusieurs personnes l'ont fait de différentes manières:

http://websmartdesign.nz/searching-structured-post-data-with-wordpress/https://adambalee.com/search-wordpress-by-custom-fields-without-a-plugin/

5
user67624

Voici une réponse améliorée d'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'];
    }

    //make sure that this filter will fire only once for the meta query
    remove_filter( 'get_meta_sql', 'me_replace_and_with_or' );
    return $sql;
}

add_filter( 'pre_get_posts', 'me_search_query');

Le problème est que WordPress génère une méta-requête avec l'opérateur "AND" et n'affiche que les publications qui ont une chaîne de recherche aux deux endroits - titre AND méta ou contenu AND méta. Nous devons donc créer un filtre supplémentaire pour remplacer "ET" par "OU" (puis supprimer ce filtre pour ne rien casser d’autre).

0
Sergey Zaharchenko

Je ne suis pas sûr, mais pour saisir toutes les clés/valeurs de champs personnalisés pour la recherche par défaut, il faudrait un appel à la base de données à l'aide de wpdb .

Les plugins alternatifs en plus de ceux de goto10 sont une solution beaucoup plus simple. Tout rechercher , WP Recherche de champs personnalisés

0
Wyck