web-dev-qa-db-fra.com

Comment puis-je améliorer cet extrait de requête d'administrateur pour éviter de générer des résultats en double sur des recherches non méta?

J'ai joué avec des extraits de code qui ajoutent des métadonnées aux recherches de l'administrateur.

Le meilleur extrait que j'ai trouvé a été écrit par Stefano sur cette question .

Cependant, il semble y avoir un bug ennuyeux lors de la recherche de termes non méta.

Voici quelques captures de mon installation de développeur local. J'ai imprimé les 2 requêtes MySQL à l'écran.

Vue du poste CPT que j'utilise pour tester

View of the single CPT post I'm using to test

C’est le code qui fonctionne comme prévu et me permettant de rechercher des métadonnées à partir de l’administrateur

This is the code working as expected and allowing me to search meta data from admin

Malheureusement, le code crée des doublons sur les correspondances non méta, dans ce cas sur le titre du post

Unfortunately the code creates duplicates on non-meta matches, in this case on post title

Un grappin indiquant le statut de la publication, le type de publication et les ancêtres de publication de dupes

! Un grappin indiquant le statut, le type et les ancêtres des dupes

Voici le code que je lance, il est fondamentalement le même que celui de Stefano, mais avec mes tentatives grossières de faire fonctionner la requête.

/*
 * Search custom fields from admin keyword searches
 */

function rel_search_join( $join ) {
    global $pagenow, $wpdb;
    if ( is_admin() && $pagenow == 'edit.php' && $_GET['post_type'] == 'listings' && $_GET['s'] != '') {    
        $join .= 'LEFT JOIN ' . $wpdb->postmeta . ' ON '. $wpdb->posts . '.ID = ' . $wpdb->postmeta . '.post_id ';
    }
    echo '<br><strong>JOIN</strong>: ';
    print_r ( $join );
    echo '<br>';
    return $join;
}
add_filter('posts_join', 'rel_search_join' );

function rel_search_where( $where ) {
    global $pagenow, $wpdb;
    if ( is_admin() && $pagenow == 'edit.php' && $_GET['post_type']=='listings' && $_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 = str_replace( "OR wp_posts.post_status = 'pending'", "", $where );
        $where = str_replace( "OR wp_posts.post_status = 'private'", "", $where );
        $where = str_replace( "OR wp_posts.post_status = 'draft'", "", $where );
        $where = str_replace( "OR wp_posts.post_status = 'future'", "", $where );
    }
    echo '<br><strong>WHERE</strong>: ';
    print_r ( $where );
    echo '<br>';
    return $where;
}
add_filter( 'posts_where', 'rel_search_where' );  
11
jnthnclrk

Une instruction GROUP BY peut regrouper vos publications après la JOIN. Pour Wordpress, vous pouvez utiliser le filtre posts_groupby .

add_filter( 'posts_groupby', 'my_post_limits' );
function my_post_limits($groupby) {
    global $pagenow, $wpdb;
    if ( is_admin() && $pagenow == 'edit.php' && $_GET['post_type']=='listings' && $_GET['s'] != '' ) {
        $groupby = "$wpdb->posts.ID";
    }
    return $groupby;
}
11
epilektric

Merci pour votre travail là-dessus, mes amis. Ce code m'a permis de faire presque tout le chemin, mais en utilisant WP 3.8, j'avais une erreur SQL non unique de table/alias, j'ai donc apporté des modifications. Pour que cela fonctionne sur ma configuration, j'ai dû définir un alias $ wpdb-> postmeta utilisé dans l'instruction JOIN. Je vérifie également une seule vérification pour voir si les crochets doivent être utilisés afin qu'ils ne tirent pas à chaque fois. J'espère que cela aide quelqu'un!

global $postmeta_alias, $is_specials_search;
$cpt_name = 'special';
$postmeta_alias = 'pdpm'; // Change this to whatever your custom post type is
$is_specials_search = is_admin() && $pagenow=='edit.php' && isset( $_GET['post_type'] ) && $_GET['post_type']==$cpt_name && isset( $_GET['s'] );

// Extend search to include 'description' field
if ( $is_specials_search ) {
  add_filter( 'posts_join',      'pd_description_search_join' );
  add_filter( 'posts_where',     'pd_description_search_where' );
  add_filter( 'posts_groupby',   'pd_search_dupe_fix' );
}

function pd_description_search_join ($join){
  global $pagenow, $wpdb, $postmeta_alias, $is_specials_search;

  if ( $is_specials_search )  
    $join .='LEFT JOIN '.$wpdb->postmeta. ' as ' . $postmeta_alias . ' ON '. $wpdb->posts . '.ID = ' . $postmeta_alias . '.post_id ';

  return $join;
} // END search_join

function pd_description_search_where( $where ){
  global $pagenow, $wpdb, $postmeta_alias, $is_specials_search;

  if ( $is_specials_search )
    $where = preg_replace(
     "/\(\s*".$wpdb->posts.".post_title\s+LIKE\s*(\'[^\']+\')\s*\)/",
     "(".$wpdb->posts.".post_title LIKE $1) OR (".$postmeta_alias.".meta_value LIKE $1)", $where );

  return $where;
} // END search_where

function pd_search_dupe_fix($groupby) {
    global $pagenow, $wpdb, $is_specials_search;

    if ( $is_specials_search )
      $groupby = "$wpdb->posts.ID";

    return $groupby;
} // END pd_search_dupe_fix
4
souverian