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

11

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

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

Cependant, il semble avoir 1 bogue ennuyeux lors de la recherche de termes non méta.

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

Vue du seul post CPT que j'utilise pour tester

Vue du seul post CPT que j'utilise pour tester

C'est le code qui fonctionne comme prévu et qui me permet de rechercher des métadonnées auprès de l'administrateur

C'est le code qui fonctionne comme prévu et qui me permet de rechercher des métadonnées auprès de l'administrateur

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

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

Une capture montrant le statut du post, le type de post et les ancêtres des dupes

! Une capture montrant le statut du post, le type de post et les ancêtres des dupes

Voici le code que j'utilise, il est fondamentalement le même que celui de Stefano, mais avec mes tentatives grossières pour 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' );  
jnthnclrk
la source
Peut-être qu'il répertorie également les révisions?
passatgt
Je pensais que je ne regardais que les publications, car j'avais supprimé les projets en attente, privés, brouillons et futurs. Je n'ai pas remarqué de type de révision.
jnthnclrk
Hmmm, ne semble pas être un statut de "révisions": codex.wordpress.org/Post_Status
jnthnclrk
essayez d'imprimer_r le type de post ou l'identifiant du post dans l'une des colonnes, je pense que les révisions sont des types de post, donc si vous pouvez voir les révisions, vous l'avez aussi dans les résultats. Mais je peux également voir que vous affichez uniquement les résultats du type de publication des annonces, donc je pense que je me trompe. Mais ça vaut le coup :)
passatgt
Ajout d'une nouvelle capture avec les statuts de publication, les types de publication et les ancêtres de publication.
jnthnclrk

Réponses:

11

Une GROUP BYdéclaration peut regrouper vos messages après le JOIN. Pour Wordpress, vous pouvez utiliser le posts_groupbyfiltre.

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;
}
épilektric
la source
4

Merci pour votre travail là-dessus, les amis. Ce code m'a permis de faire la plupart du chemin, mais en utilisant WP 3.8, j'obtenais une erreur de table / alias non unique SQL, j'ai donc apporté quelques 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 fois pour voir si les crochets doivent être utilisés afin qu'ils ne se déclenchent 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
souveraine
la source