Estensione del contesto di ricerca nella schermata dei post dell'elenco di amministratori


34

Ho creato un tipo di post personalizzato e vi ho allegato alcuni campi personalizzati. Ora vorrei che gli autori potessero eseguire la ricerca nella schermata dell'elenco dei post personalizzati (nel back-end dell'amministratore) per essere eseguiti anche sui meta-campi e non solo nel titolo e nei contenuti come al solito.

Dove posso collegarmi e quale codice devo usare?

Immagine di esempio inserisci qui la descrizione dell'immagine

Stefano


1
Una vecchia domanda, ma ... vorrei suggerire di nascondere indirizzi e-mail e nomi dagli screenshot ...
Erenor Paz

Risposte:


37

Ho risolto il filtro della query aggiungendo il join sulla tabella postmeta e modificando la clausola where. suggerimenti su come filtrare la clausola WHERE (spesso richiedono la ricerca e la sostituzione di espressioni regolari) sono qui sul codice :

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;
}

1
Wow! Proprio quello che stavo cercando. Tuttavia, penso che potrei aver trovato un bug, quando cerco sul titolo del post, ottengo una corrispondenza che viene quindi duplicata nei risultati 5 volte!?! imgur.com/eE52gIA
jnthnclrk il

Ecco un altro problema con l'SQL stampato: tinypic.com/view.php?pic=124tqb6&s=5 Non riesco a capire perché ottengo 5 elementi!?!
jnthnclrk,

1
Ha

Questo e il post in basso mi sono stati utili. Ora per trovare un modo per includere la ricerca dell'autore del post e mostrare i post fatti da loro.
Shawn Rebelo,

@Stefano, il risultato della ricerca sta funzionando. Hai un problema, campo predefinito "Pubblica titolo", il record di ricerca si ripete più volte e lato amministratore. Vedi: imgur.com/a/W4wmXhO
Super Model il

10

La risposta di Stefano è ottima ma manca una clausola distinta:

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' );

Aggiungi il codice sopra aggiornalo e funzionerà senza duplicati.


7

Questo funzionerà,

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");

1
Ti preghiamo di indentare correttamente il tuo codice e includere una spiegazione del perché e come funzionerà .
martedì

Anche se l'ho votato per la prima volta, mi sono reso conto che questo, sfortunatamente, funzionerà su ogni ricerca allo stesso modo, potrebbe interrompere la ricerca del front-end.
Maciej Paprocki,

L'aggiunta di un segno di spunta if ( $query->query['post_type'] != 'your_custom_post_type' ){ return; }nella parte superiore della funzione interromperà l'esecuzione di altre ricerche. Nota che la tecnica in questa risposta non cerca più il post_title e aggiungerlo nuovamente non è banale.
jwinn,

Un ulteriore problema: l'indicatore Cerca risultati per "<keyword>" chiamate get_search_query()che chiama ulteriormente get_query_var( 's' ). Poiché "s" è impostato su stringa vuota, i risultati della ricerca per "" avranno sempre un valore vuoto tra virgolette. C'è una modifica a questa soluzione che aggira questo?
jschrab

1

Risposta 1: aggiungi questo codice nel file di funzione e modifica e aggiungi il nome di più colonne che hai utilizzato nel tuo tipo di post personalizzato

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' );

Risposta 2: consigliato Utilizzare questo codice nel file di funzione senza alcuna modifica

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' );

0

Non è una ricerca, ma alcuni "selezionano" per valore distinto.

Nel file di functions-iworks-posts-filter.zip Hai un esempio come aggiungere filtro per posta ordinaria da parte di alcuni meta_key. Penso che sia facile da convertire.


grazie per l'aiuto ... Vado a vedere il tuo allegato in questo momento. Ti farò sapere i risultati della mia indagine ;-) Stefano
Stefano

Marcin Penso che ti riferisca ai filtri come "per data" ecc ... ma devo agganciare il campo "ricerca libera" sopra. Comunque ho appena pubblicato la mia soluzione, forse aiuta Grazie comunque!
Stefano

0

La versione del codice qui in un paio di risposte che modifica il parametro meta_query del WP_Query della ricerca in pre_get_posts non cercava più il post_title. Aggiungendo la possibilità di cercare il titolo del post, OPPURE i valori meta non possono essere eseguiti direttamente in WP_Query senza modificare sfortunatamente SQL, poiché questa domanda si sviluppa su: Utilizzo di meta query ('meta_query') con una query di ricerca ('s')

Ho combinato alcune delle tecniche qui per ottenere una versione funzionante che eviti preg_replaces e troppe modifiche SQL (vorrei che potesse essere evitato del tutto). L'unico aspetto negativo è che dopo una ricerca, il testo dei sottotitoli nella parte superiore della pagina indica "Risultati della ricerca per ''". L'ho appena nascosto con CSS per il tipo di post personalizzato del mio plugin.

/**
 * 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');
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.