¿Cómo mejoro este fragmento de consulta de administrador para evitar generar resultados duplicados en búsquedas no meta?

11

He estado jugando con fragmentos de código que agregan metadatos a las búsquedas administrativas.

El mejor fragmento que encontré fue escrito por Stefano sobre esta pregunta .

Sin embargo, parece tener 1 error molesto al buscar términos no meta.

Aquí hay algunas capturas de mi instalación de desarrollo local. Imprimí las 2 consultas MySQL en la pantalla.

Vista de la única publicación de CPT que estoy usando para probar

Vista de la única publicación de CPT que estoy usando para probar

Este es el código que funciona como se esperaba y me permite buscar metadatos del administrador

Este es el código que funciona como se esperaba y me permite buscar metadatos del administrador

Desafortunadamente, el código crea duplicados en coincidencias no meta, en este caso en el título de la publicación

Desafortunadamente, el código crea duplicados en coincidencias no meta, en este caso en el título de la publicación

Una captura que muestra el estado de la publicación, el tipo de publicación y los antepasados ​​de los engañados

! Una captura que muestra el estado de la publicación, el tipo de publicación y los antepasados ​​de los engañados

Aquí está el código que estoy ejecutando, es básicamente el mismo que el de Stefano, pero con mis crudos intentos de hacer que la consulta funcione.

/*
 * 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
fuente
¿Quizás también enumere las revisiones?
Passatgt
Pensé que solo estaba mirando publicado, porque eliminé pendientes, privados, borradores y futuros. No noté un tipo de revisión.
jnthnclrk
Hmmm, no parece ser un estado de "revisiones": codex.wordpress.org/Post_Status
jnthnclrk
intente imprimir_r el tipo de publicación o el ID de publicación en una de las columnas, creo que las revisiones son tipos de publicación, por lo que si puede ver las revisiones, también lo tiene en los resultados. Pero también puedo ver que solo muestra resultados del tipo de publicación de listados, así que creo que estoy equivocado. Pero vale la pena intentarlo :)
Passatgt
Se agregó una nueva captura con estados de publicaciones, tipos de publicaciones y antepasados ​​de publicaciones.
jnthnclrk

Respuestas:

11

Una GROUP BYdeclaración puede agrupar sus publicaciones después de JOIN. Para Wordpress puedes usar el posts_groupbyfiltro.

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;
}
epilektric
fuente
4

Gracias por su trabajo en esto, amigos. Este código me llevó casi todo el camino, pero al usar WP 3.8 estaba obteniendo un error de tabla / alias no único de SQL, así que hice algunos cambios. Para que funcione en mi configuración, tuve que establecer un alias $ wpdb-> postmeta que se usó en la declaración JOIN. También verifico solo verifica una vez para ver si los ganchos deben usarse para que no se disparen siempre. ¡Espero que esto ayude a alguien!

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
souverian
fuente