Ampliar el contexto de búsqueda en la pantalla de publicación de la lista de administradores

34

He creado un tipo de publicación personalizada y le he adjuntado algunos campos personalizados. Ahora me gustaría que la búsqueda que los autores pueden realizar en la pantalla de la lista de publicaciones personalizada (en el backend de administración) también se realice en los metacampos y no solo se vea en el título y el contenido como de costumbre.

¿Dónde puedo conectarme y qué código tengo que usar?

Imagen de ejemplo ingrese la descripción de la imagen aquí

Stefano

Stefano
fuente
1
Una vieja pregunta, pero ... me gustaría sugerir ocultar las direcciones de correo electrónico y los nombres de las capturas de pantalla ...
Erenor Paz

Respuestas:

37

Resolví filtrar la consulta agregando la unión en la tabla postmeta y cambiando la cláusula where. Aquí encontrará consejos sobre cómo filtrar la cláusula WHERE (a menudo requieren búsqueda y reemplazo de expresiones regulares) en el códice :

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
fuente
1
¡Guauu! Justo lo que he estado buscando. Sin embargo, creo que encontré un error, cuando busco en el título de la publicación, obtengo una coincidencia que luego se duplica en los resultados 5 veces. imgur.com/eE52gIA
jnthnclrk
Aquí hay otra captura con el SQL impreso: tinypic.com/view.php?pic=124tqb6&s=5 ¡ No puedo entender por qué recibo 5 artículos!?!
jnthnclrk
1
Ha
Esto y la publicación a continuación me fueron útiles. Ahora para encontrar una manera de incluir la búsqueda del autor de la publicación y mostrar las publicaciones realizadas por ellos.
Shawn Rebelo
@Stefano, el resultado de búsqueda está funcionando. Tiene un problema, el campo predeterminado "Título de la publicación", el registro de búsqueda se repite muchas veces y el lado administrativo. Ver: imgur.com/a/W4wmXhO
Super Model
10

La respuesta de Stefano es excelente, pero carece de una cláusula 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' );

Agregue el código anterior, actualícelo y funcionará sin duplicados.

Calara Ionut
fuente
7

Esto funcionará

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
fuente
1
Por favor, sangra adecuadamente tu código e incluye una explicación de por qué y cómo funcionará .
desde el
Aunque lo voté por primera vez, me di cuenta de que, desafortunadamente, funcionará en cada búsqueda de la misma manera que podría romper la búsqueda frontal.
Maciej Paprocki
Agregar una marca para la if ( $query->query['post_type'] != 'your_custom_post_type' ){ return; }parte superior de la función evitará que esto se ejecute en otras búsquedas. Tenga en cuenta que la técnica en esta respuesta ya no busca el post_title y agregar eso nuevamente no es trivial.
jwinn
Otro problema: el indicador Resultados de búsqueda para llamadas de "<palabra clave>"get_search_query() que llaman más get_query_var( 's' ). Como "s" está configurado como una cadena vacía, los resultados de búsqueda para "" siempre tendrán un valor vacío entre las comillas. ¿Hay alguna modificación en esta solución que evite esto?
jschrab
1

Respuesta 1: Agregue este código en el archivo de función, y cambie y agregue más nombres de columnas, que ha utilizado en su tipo de publicación personalizada

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

Respuesta 2: Recomendado Use este código en el archivo de función sin ningún cambio

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' );
Súper modelo
fuente
0

No es una búsqueda, pero algunos "seleccionan" por un valor distinto.

En el archivo funciones-iworks-posts-filter.zip Tienes un ejemplo de cómo agregar filtro para la publicación regular por alguna meta_key. Creo que es fácil de convertir.

Marcin
fuente
gracias por la ayuda ... Voy a ver su adjunto en este momento. Le haré saber los resultados de mi investigación ;-) Stefano
Stefano
Marcin Creo que se está refiriendo a los filtros como "por fecha", etc. ... pero necesito conectar el campo de "búsqueda gratuita" arriba. De todos modos, acabo de publicar mi solución, tal vez ayude ¡Gracias de todos modos!
Stefano
0

La versión del código aquí en un par de respuestas que modifica el parámetro meta_query de la búsqueda WP_Query en pre_get_posts ya no estaba buscando el post_title. Agregar la capacidad de buscar el título de la publicación, O los meta valores no se pueden hacer directamente en WP_Query sin modificar SQL desafortunadamente, ya que esta pregunta se desarrolla sobre: Usar metaconsulta ('meta_query') con una consulta de búsqueda ('s')

He combinado algunas de las técnicas aquí para obtener una versión funcional que evite los preg_replaces y demasiadas modificaciones de SQL (desearía que se pudiera evitar por completo). El único inconveniente es que después de una búsqueda, el texto de los subtítulos en la parte superior de la página dice "Resultados de búsqueda para ''". Acabo de ocultar eso con CSS para el tipo de publicación personalizada de mi complemento.

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