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

11

Ich habe mit Codefragmenten herumgespielt, die Metadaten zur Administratorsuche hinzufügen.

Das beste Snippet, das ich gefunden habe, wurde von Stefano zu dieser Frage geschrieben .

Es scheint jedoch einen nervigen Fehler bei der Suche nach Nicht-Meta-Begriffen zu geben.

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

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

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

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

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

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

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

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

! Ein Grab, das den Post-Status, den Post-Typ und die Post-Vorfahren von Dupes zeigt

Hier ist der Code, den ich ausführe. Er ist im Grunde der gleiche 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' );  
jnthnclrk
quelle
Vielleicht listet es auch die Revisionen auf?
passatgt
Ich dachte, ich schaue nur auf veröffentlicht, weil ich ausstehende, private, Draft & Future entfernt habe. Ich habe keinen Revisionstyp bemerkt.
jnthnclrk
Hmmm, scheint kein "Revisions" -Status zu sein: codex.wordpress.org/Post_Status
jnthnclrk
Versuchen Sie, den Beitragstyp oder die Beitrags-ID in einer der Spalten zu drucken. Ich denke, Revisionen sind Beitragstypen. Wenn Sie also Revisionen sehen können, haben Sie dies auch in den Ergebnissen. Aber ich kann auch sehen, dass Sie nur Ergebnisse aus dem Eintragstyp anzeigen, also denke ich, dass ich falsch liege. Aber es ist einen Versuch wert :)
passatgt
Es wurde ein neuer Grab mit Post-Status, Post-Typen und Post-Vorfahren hinzugefügt.
jnthnclrk

Antworten:

11

Eine GROUP BYAnweisung kann Ihre Beiträge nach dem gruppieren JOIN. Für Wordpress können Sie den posts_groupbyFilter 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;
}
epilektrisch
quelle
4

Vielen Dank für Ihre Arbeit, Leute. Dieser Code hat mich größtenteils dorthin gebracht, aber mit WP 3.8 wurde ein nicht eindeutiger SQL-Tabellen- / Alias-Fehler angezeigt, sodass ich einige Änderungen vorgenommen habe. Damit es in meinem Setup funktioniert, musste ich einen $ wpdb-> postmeta-Alias ​​festlegen, 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
souverian
quelle