Memperluas konteks pencarian di layar posting daftar admin


34

Saya telah membuat jenis posting khusus dan telah melampirkan beberapa bidang khusus untuknya. Sekarang saya ingin pencarian yang penulis dapat lakukan pada layar daftar posting kustom (di admin backend) juga dilakukan pada bidang meta dan tidak hanya melihat pada judul dan konten seperti biasa.

Di mana saya bisa menghubungkan dan kode apa yang harus saya gunakan?

Contoh gambar masukkan deskripsi gambar di sini

Stefano


1
Sebuah pertanyaan lama, tapi..saya ingin menyarankan untuk menyembunyikan alamat email dan nama dari tangkapan layar ...
Erenor Paz

Jawaban:


37

Saya memecahkan pemfilteran kueri dengan menambahkan gabungan pada tabel postmeta dan mengubah klausa where. tips untuk memfilter klausa WHERE (seringkali membutuhkan pencarian & penggantian ekspresi reguler) ada di sini di 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;
}

1
Wow! Apa yang saya cari. Namun, saya pikir saya mungkin menemukan bug, ketika mencari pada judul posting, saya mendapatkan kecocokan yang kemudian diduplikasi dalam hasil 5 kali!?! imgur.com/eE52gIA
jnthnclrk

Berikut ini adalah contoh lain dari SQL yang dicetak: tinypic.com/view.php?pic=124tqb6&s=5 Tidak dapat mengetahui mengapa saya mendapatkan 5 item!?!
jnthnclrk

1
Diposting pertanyaan terpisah tentang cara memperbaiki bug dupe: wordpress.stackexchange.com/questions/111185/…
jnthnclrk

Ini dan pos di bawah berguna bagi saya. Sekarang untuk menemukan cara memasukkan pencarian penulis posting dan menunjukkan posting yang dilakukan oleh mereka.
Shawn Rebelo

@Stefano, hasil pencarian berfungsi. Memiliki masalah, bidang default "Judul posting", catatan pencarian berulang kali dan sisi admin. Lihat: imgur.com/a/W4wmXhO
Super Model

10

Jawaban Stefano bagus tetapi tidak memiliki klausa yang berbeda:

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

Tambahkan kode di atas perbarui dan itu akan bekerja tanpa duplikat.


7

Ini akan bekerja,

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
Mohon indentasi kode Anda dengan benar, dan sertakan penjelasan mengapa dan bagaimana ini akan bekerja .
tfrommen

Meskipun saya pertama kali memutakhirkannya, saya menyadari bahwa ini akan, sayangnya, bekerja pada setiap pencarian ini mungkin merusak pencarian front-end.
Maciej Paprocki

Menambahkan tanda centang untuk if ( $query->query['post_type'] != 'your_custom_post_type' ){ return; }bagian atas fungsi akan menghentikan ini dari pencarian lainnya. Perhatikan bahwa teknik dalam jawaban ini tidak lagi mencari post_title dan menambahkan bahwa kembali tidak sepele.
jwinn

Satu masalah lebih lanjut - Hasil pencarian indikator untuk panggilan "<keyword>" yang panggilan get_search_query()selanjutnya get_query_var( 's' ). Karena "s" disetel ke string kosong, hasil pencarian untuk "" akan selalu memiliki nilai kosong di antara tanda kutip. Apakah ada perubahan pada solusi ini yang mengatasi ini?
jschrab

1

Jawaban 1: Tambahkan kode ini dalam file fungsi, dan ubah dan tambahkan lebih banyak nama kolom, yang telah Anda gunakan dalam jenis posting kustom Anda

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

Jawaban 2: Disarankan Gunakan kode ini dalam file fungsi tanpa perubahan apa pun

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

Ini bukan pencarian, tetapi beberapa "pilih" dengan nilai berbeda.

Dalam file functions-iworks-posts-filter.zip Anda memiliki contoh cara menambahkan filter untuk posting biasa oleh beberapa meta_key. Saya pikir itu mudah untuk dikonversi.


terima kasih atas bantuannya ... Saya akan melihat attachmend Anda sekarang. Saya akan memberi tahu Anda hasil penyelidikan saya ;-) Stefano
Stefano

Marcin Saya pikir Anda mereferensikan ke filter seperti "berdasarkan tanggal" dll ... tapi saya perlu menghubungkan bidang "pencarian gratis" di atas. Pokoknya saya baru memposting solusi saya, mungkin itu membantu Terima kasih pula!
Stefano

0

Versi kode di sini dalam beberapa jawaban yang mengubah parameter meta_query dari WP_Query pencarian di pre_get_posts tidak lagi mencari post_title. Menambahkan kemampuan untuk mencari judul posting, ATAU nilai-nilai meta tidak dapat dilakukan secara langsung di WP_Query tanpa memodifikasi SQL, sayangnya, karena pertanyaan ini menguraikan: Menggunakan kueri meta ('meta_query') dengan kueri penelusuran ('s')

Saya telah menggabungkan beberapa teknik di sini untuk mendapatkan versi yang berfungsi yang menghindari preg_replaces dan terlalu banyak modifikasi SQL (saya berharap ini bisa dihindari sepenuhnya). Satu-satunya downside adalah bahwa setelah pencarian, teks subtitle di bagian atas halaman mengatakan "Hasil pencarian untuk ''". Saya baru saja menyembunyikannya dengan CSS untuk jenis posting khusus plugin saya.

/**
 * 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');
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.