Erweitern des Suchkontexts im Bildschirm zum Posten der Administratorliste

34

Ich habe einen benutzerdefinierten Beitragstyp erstellt und ihm einige benutzerdefinierte Felder angehängt. Nun möchte ich, dass die Suche, die Autoren auf dem benutzerdefinierten Postlistenbildschirm (im Admin-Backend) durchführen können, auch auf den Metafeldern durchgeführt wird und nicht nur wie gewohnt in Titel und Inhalt nachgeschaut wird.

Wo kann ich mich einhängen und welchen Code muss ich verwenden?

Beispielbild Bildbeschreibung hier eingeben

Stefano

Stefano
quelle
1
Eine alte Frage, aber ich möchte vorschlagen, E-Mail-Adressen und Namen aus den Screenshots zu verbergen ...
Erenor Paz

Antworten:

37

Ich habe das Filtern der Abfrage gelöst, indem ich den Join der Postmeta-Tabelle hinzugefügt und die where-Klausel geändert habe. Tipps zum Filtern der WHERE-Klausel (häufig das Suchen und Ersetzen mit regulären Ausdrücken erforderlich) finden Sie hier im Codex :

add_filter( 'posts_join', 'segnalazioni_search_join' );
function segnalazioni_search_join ( $join ) {
    global $pagenow, $wpdb;

    // I want the filter only when performing a search on edit page of Custom Post Type named "segnalazioni".
    if ( is_admin() && 'edit.php' === $pagenow && 'segnalazioni' === $_GET['post_type'] && ! empty( $_GET['s'] ) ) {    
        $join .= 'LEFT JOIN ' . $wpdb->postmeta . ' ON ' . $wpdb->posts . '.ID = ' . $wpdb->postmeta . '.post_id ';
    }
    return $join;
}

add_filter( 'posts_where', 'segnalazioni_search_where' );
function segnalazioni_search_where( $where ) {
    global $pagenow, $wpdb;

    // I want the filter only when performing a search on edit page of Custom Post Type named "segnalazioni".
    if ( is_admin() && 'edit.php' === $pagenow && 'segnalazioni' === $_GET['post_type'] && ! empty( $_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 );
    }
    return $where;
}
Stefano
quelle
1
Wow! Genau das, wonach ich gesucht habe. Ich glaube jedoch, dass ich einen Fehler gefunden habe, wenn ich nach dem Post-Titel suche, erhalte ich eine Übereinstimmung, die dann 5-mal in den Ergebnissen dupliziert wird!?! imgur.com/eE52gIA
jnthnclrk
Hier ist ein weiteres Beispiel für den SQL- Code : tinypic.com/view.php?pic=124tqb6&s=5 Ich kann nicht herausfinden, warum ich 5 Artikel erhalte!?!
jnthnclrk
1
Geposted eine separate Frage zur Behebung des Fehlers: wordpress.stackexchange.com/questions/111185/…
jnthnclrk
Dies und der folgende Beitrag waren für mich nützlich. Hier finden Sie eine Möglichkeit, den Beitragsautor zu suchen und die von ihm erstellten Beiträge anzuzeigen.
Shawn Rebelo
@Stefano, Suchergebnis funktioniert. Haben Sie ein Problem, Standardfeld "Beitragstitel", Suchdatensatz wiederholt sich oft und Admin-Seite. Siehe: imgur.com/a/W4wmXhO
Super Model
10

Stefano Antwort ist toll, aber es fehlt eine eindeutige Klausel:

function segnalazioni_search_distinct( $where ){
    global $pagenow, $wpdb;

    if ( is_admin() && $pagenow=='edit.php' && $_GET['post_type']=='segnalazioni' && $_GET['s'] != '') {
    return "DISTINCT";

    }
    return $where;
}
add_filter( 'posts_distinct', 'segnalazioni_search_distinct' );

Füge den obigen Code hinzu, aktualisiere ihn und er funktioniert ohne Duplikate.

Calara Ionut
quelle
7

Das wird funktionieren,

function custom_search_query( $query ) {
    $custom_fields = array(
        // put all the meta fields you want to search for here
        "rg_first_name",
        "rg_1job_designation"
    );
    $searchterm = $query->query_vars['s'];

    // we have to remove the "s" parameter from the query, because it will prevent the posts from being found
    $query->query_vars['s'] = "";

    if ($searchterm != "") {
        $meta_query = array('relation' => 'OR');
        foreach($custom_fields as $cf) {
            array_push($meta_query, array(
                'key' => $cf,
                'value' => $searchterm,
                'compare' => 'LIKE'
            ));
        }
        $query->set("meta_query", $meta_query);
    };
}
add_filter( "pre_get_posts", "custom_search_query");
Vin_fugen
quelle
1
Bitte rücken Sie Ihren Code richtig ein und erläutern Sie, warum und wie dies funktioniert .
Beginn am
Obwohl ich es zuerst hochgestuft habe, wurde mir klar, dass dies leider bei jeder Suche funktioniert, auch wenn die Front-End-Suche dadurch möglicherweise unterbrochen wird.
Maciej Paprocki
Durch das Hinzufügen eines Häkchens für if ( $query->query['post_type'] != 'your_custom_post_type' ){ return; }top oben in der Funktion wird verhindert, dass diese bei anderen Suchvorgängen ausgeführt wird. Beachten Sie, dass die Technik in dieser Antwort nicht mehr den post_title durchsucht und das Hinzufügen dieses Back-Ins nicht trivial ist.
30.
Ein weiteres Problem - Der Indikator Suchergebnisse für "<Schlüsselwort>" Anrufe, get_search_query()die weitere Anrufe get_query_var( 's' ). Da "s" als leere Zeichenfolge festgelegt ist, wird in den Suchergebnissen für "" zwischen den Anführungszeichen immer ein leerer Wert angezeigt. Gibt es eine Verbesserung an dieser Lösung, die dies umgeht?
Jschrab
1

Antwort 1: Fügen Sie diesen Code in die Funktionsdatei ein und ändern und fügen Sie weitere Spaltennamen hinzu, die Sie in Ihrem benutzerdefinierten Beitragstyp verwendet haben

function extend_admin_search( $query ) {

    // use your post type
    $post_type = 'document';
    // Use your Custom fields/column name to search for
    $custom_fields = array(
        "_file_name",
    );

    if( ! is_admin() )
        return;

    if ( $query->query['post_type'] != $post_type )
        return;

    $search_term = $query->query_vars['s'];

    // Set to empty, otherwise it won't find anything
    $query->query_vars['s'] = '';

    if ( $search_term != '' ) {
        $meta_query = array( 'relation' => 'OR' );

        foreach( $custom_fields as $custom_field ) {
            array_push( $meta_query, array(
                'key' => $custom_field,
                'value' => $search_term,
                'compare' => 'LIKE'
            ));
        }

        $query->set( 'meta_query', $meta_query );
    };
}

add_action( 'pre_get_posts', 'extend_admin_search' );

Antwort 2: Empfohlen Verwenden Sie diesen Code in der Funktionsdatei ohne Änderungen

function cf_search_join( $join ) {
    global $wpdb;

    if ( is_search() ) {    
        $join .=' LEFT JOIN '.$wpdb->postmeta. ' ON '. $wpdb->posts . '.ID = ' . $wpdb->postmeta . '.post_id ';
    }

    return $join;
}
add_filter('posts_join', 'cf_search_join' );
function cf_search_where( $where ) {
    global $pagenow, $wpdb;

    if ( is_search() ) {
        $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 );
    }

    return $where;
}
add_filter( 'posts_where', 'cf_search_where' );

function cf_search_distinct( $where ) {
    global $wpdb;

    if ( is_search() ) {
        return "DISTINCT";
    }

    return $where;
}
add_filter( 'posts_distinct', 'cf_search_distinct' );
Super Model
quelle
0

Es handelt sich nicht um eine Suche, sondern um eine Auswahl anhand eines bestimmten Werts.

In der Datei functions-iworks-posts-filter.zip haben Sie ein Beispiel, wie Sie Filter für reguläre Posts durch einen meta_key hinzufügen können. Ich denke, es ist leicht zu konvertieren.

Marcin
quelle
danke für die hilfe ... ich werde mir jetzt deinen attachmend ansehen. Ich werde Ihnen die Ergebnisse meiner Untersuchung mitteilen ;-) Stefano
Stefano
Marcin Ich denke, dass Sie auf die Filter wie "Nach Datum" usw. verweisen, aber ich muss das Feld "Freie Suche" oben anhaken. Wie auch immer, ich habe gerade meine Lösung gepostet, vielleicht hilft es. Danke trotzdem!
Stefano
0

Die Version des Codes hier in ein paar Antworten, die den Parameter meta_query der WP_Query der Suche in pre_get_posts ändert, hat den post_title nicht mehr durchsucht. Die Möglichkeit, entweder den Post-Titel oder die OR-Meta-Werte zu durchsuchen, kann leider nicht direkt in WP_Query durchgeführt werden, ohne SQL zu ändern.

Ich habe einige der hier beschriebenen Techniken kombiniert, um eine funktionierende Version zu erhalten, die preg_replaces und zu viele SQL-Änderungen vermeidet (ich wünschte, sie könnten vollständig vermieden werden). Der einzige Nachteil ist, dass nach einer Suche im Untertiteltext oben auf der Seite "Suchergebnisse für ''" steht. Ich habe das gerade mit CSS für den benutzerdefinierten Beitragstyp meines Plugins ausgeblendet.

/**
 * Extend custom post type search to also search meta fields
 * @param  WP_Query $query
 */
function extend_cpt_admin_search( $query ) {
  // Make sure we're in the admin area and that this is our custom post type
  if ( !is_admin() || $query->query['post_type'] != 'your_custom_post_type' ){
    return;
  }

  // Put all the meta fields you want to search for here
  $custom_fields = array(
    "your_custom_meta_field",
    "your_custom_meta_field2",
    "your_custom_meta_field3"
  );
  // The string submitted via the search form
  $searchterm = $query->query_vars['s'];

  // Set to empty, otherwise no results will be returned.
  // The one downside is that the displayed search text is empty at the top of the page.
  $query->query_vars['s'] = '';

  if ($searchterm != ""){
    // Add additional meta_query parameter to the WP_Query object.
    // Reference: https://codex.wordpress.org/Class_Reference/WP_Query#Custom_Field_Parameters
    $meta_query = array();
    foreach($custom_fields as $cf) {
      array_push($meta_query, array(
        'key' => $cf,
        'value' => $searchterm,
        'compare' => 'LIKE'
      ));
    }
    // Use an 'OR' comparison for each additional custom meta field.
    if (count($meta_query) > 1){
      $meta_query['relation'] = 'OR';
    }
    // Set the meta_query parameter
    $query->set('meta_query', $meta_query);


    // To allow the search to also return "OR" results on the post_title
    $query->set('_meta_or_title', $searchterm);
  }
}
add_action('pre_get_posts', 'extend_cpt_admin_search');



/**
 * WP_Query parameter _meta_or_title to allow searching post_title when also
 * checking searching custom meta values
 * https://wordpress.stackexchange.com/questions/78649/using-meta-query-meta-query-with-a-search-query-s
 * https://wordpress.stackexchange.com/a/178492
 * This looks a little scary, but basically it's modifying the WHERE clause in the 
 * SQL to say "[like the post_title] OR [the existing WHERE clause]"
 * @param  WP_Query $q
 */
function meta_or_title_search( $q ){
  if( $title = $q->get( '_meta_or_title' ) ){
    add_filter( 'get_meta_sql', function( $sql ) use ( $title ){
      global $wpdb;

      // Only run once:
      static $nr = 0;
      if( 0 != $nr++ ) return $sql;

      // Modified WHERE
      $sql['where'] = sprintf(
          " AND ( (%s) OR (%s) ) ",
          $wpdb->prepare( "{$wpdb->posts}.post_title LIKE '%%%s%%'", $title),
          mb_substr( $sql['where'], 5, mb_strlen( $sql['where'] ) )
      );

      return $sql;
    });
  }
}
add_action('pre_get_posts', 'meta_or_title_search');
jwinn
quelle