Jak ulepszyć ten fragment zapytania administratora, aby uniknąć generowania zduplikowanych wyników podczas wyszukiwania innych niż meta?

11

Bawiłem się fragmentami kodu, które dodają metadane do wyszukiwań administratora.

Najlepszy fragment, jaki znalazłem, został napisany przez Stefano na to pytanie .

Wydaje się jednak, że ma 1, irytujący błąd podczas wyszukiwania terminów niemeta.

Oto kilka chwytów z mojej lokalnej instalacji deweloperskiej. Wydrukowałem 2 zapytania MySQL na ekranie.

Widok jednego posta CPT, którego używam do testowania

Widok jednego posta CPT, którego używam do testowania

Ten kod działa zgodnie z oczekiwaniami i pozwala mi wyszukiwać metadane od administratora

Ten kod działa zgodnie z oczekiwaniami i pozwala mi wyszukiwać metadane od administratora

Niestety kod tworzy duplikaty przy dopasowaniach innych niż meta, w tym przypadku przy tytule postu

Niestety kod tworzy duplikaty przy dopasowaniach innych niż meta, w tym przypadku przy tytule postu

Chwyt pokazujący status postu, typ posta i post przodków duplikatów

! Chwyt pokazujący status postu, typ posta i post przodków duplikatów

Oto kod, który uruchamiam, jest w zasadzie taki sam jak kod Stefano, ale przy moich prymitywnych próbach uruchomienia zapytania.

/*
 * 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
źródło
Może zawiera też listę poprawek?
passatgt
Myślałem, że patrzę tylko na opublikowane, ponieważ usunąłem oczekujące, prywatne, szkic i przyszłość. Nie zauważyłem typu zmiany.
jnthnclrk
Hmmm, nie wydaje się być statusem „rewizji”: codex.wordpress.org/Post_Status
jnthnclrk
spróbuj print_r typu posta lub identyfikatora postu w jednej z kolumn, myślę, że wersje są typami postów, więc jeśli możesz zobaczyć wersje, masz to również w wynikach. Ale widzę też, że wyświetlasz tylko wyniki z typu wpisu na liście, więc myślę, że się mylę. Ale warto spróbować :)
passatgt
Dodano nowy chwyt ze statusem postu, typami postów i przodkami postów.
jnthnclrk

Odpowiedzi:

11

GROUP BYStwierdzenie można grupować swoje posty po JOIN. W przypadku Wordpress możesz użyć posts_groupbyfiltra.

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;
}
epilektryczny
źródło
4

Dzięki za pracę nad tym, ludzie. Ten kod zapewnił mi większość możliwości, ale używając WP 3.8 otrzymywałem nieunikalny błąd SQL / błąd aliasu, więc wprowadziłem kilka zmian. Aby działało w mojej konfiguracji, musiałem ustawić alias $ wpdb-> postmeta, który był używany w instrukcji JOIN. Sprawdzam też tylko raz, aby sprawdzić, czy należy użyć haczyków, aby za każdym razem nie strzelały. Mam nadzieję, że to komuś pomoże!

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
źródło