web-dev-qa-db-de.com

Wie verbessere ich dieses Administrator-Abfrage-Snippet, um zu vermeiden, dass bei Nicht-Meta-Suchen doppelte Ergebnisse generiert werden?

Ich habe mit Codefragmenten herumgespielt, die den Administratorsuchen Metadaten hinzufügen.

Der beste Ausschnitt, den ich gefunden habe, wurde von Stefano zu dieser Frage geschrieben .

Es scheint jedoch einen lästigen Fehler bei der Suche nach Nicht-Meta-Begriffen zu haben.

Hier sind einige Beispiele meiner lokalen Entwicklerinstallation. Ich habe die 2 MySQL-Abfragen auf den Bildschirm gedruckt.

Ansicht des einzelnen CPT-Beitrags, den ich zum Testen verwende

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

Dies ist der Code, der wie erwartet funktioniert und es mir ermöglicht, Metadaten von admin zu durchsuchen

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

Leider erstellt der Code Duplikate für Nicht-Meta-Übereinstimmungen, in diesem Fall für den Post-Titel

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

Ein Grab, der den Post-Status, den Post-Typ und die Post-Vorfahren von Dupes anzeigt

! Ein Grab, der den Post-Status, den Post-Typ und die Post-Vorfahren von Dupes anzeigt

Hier ist der Code, den ich ausführe. Er ist im Grunde derselbe wie der von Stefano, aber mit meinen groben Versuchen, die Abfrage zum Laufen zu bringen.

/*
 * 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

Eine GROUP BY-Anweisung kann Ihre Posts nach der JOIN gruppieren. Für Wordpress können Sie den posts_groupby Filter verwenden.

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

Vielen Dank für Ihre Arbeit, Leute. Mit diesem Code bin ich meistens dorthin gekommen, aber unter Verwendung von WP 3.8 wurde ein nicht eindeutiger SQL-Tabellen-/Aliasfehler gemeldet, sodass ich einige Änderungen vorgenommen habe. Damit es in meinem Setup funktioniert, musste ich einen $ wpdb-> postmeta-Alias ​​setzen, der in der JOIN-Anweisung verwendet wurde. Ich überprüfe auch nur einmal, ob die Haken verwendet werden sollten, damit sie nicht jedes Mal ausgelöst werden. Hoffe das hilft jemandem!

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