Estendendo o contexto de pesquisa na tela de postagem da lista de administradores

34

Eu criei um tipo de postagem personalizado e anexei alguns campos personalizados a ele. Agora, gostaria que a pesquisa que os autores possam realizar na tela da lista de postagens personalizadas (no back-end do administrador) também fosse realizada nos meta-campos e não apenas no título e no conteúdo, como de costume.

Onde posso conectar-me e qual código devo usar?

Imagem de exemplo insira a descrição da imagem aqui

Stefano

Stefano
fonte
11
Uma questão antiga, but..i gostaria de sugerir aos endereços de e-mail esconder e nomes das imagens ...
Erenor Paz

Respostas:

37

Resolvi filtrar a consulta adicionando a junção na tabela postmeta e alterando a cláusula where. dicas sobre como filtrar a cláusula WHERE (geralmente exigem pesquisa e substituição de expressões regulares) estão aqui no 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
fonte
11
Uau! Apenas o que eu estava procurando. No entanto, acho que encontrei um bug. Ao pesquisar no título do post, recebo uma correspondência que é duplicada nos resultados 5 vezes!?! imgur.com/eE52gIA
jnthnclrk
Aqui está outra questão com o SQL impresso: tinypic.com/view.php?pic=124tqb6&s=5 Não consigo descobrir por que recebo 5 itens!?!
Jnthnclrk
11
Postou uma pergunta separada para corrigir o bug dupe: wordpress.stackexchange.com/questions/111185/...
jnthnclrk
Este e o post abaixo foram úteis para mim. Agora, encontre uma maneira de incluir a pesquisa do autor da postagem e mostrar as postagens feitas por eles.
Shawn Rebelo
@ Stefano, o resultado da pesquisa está funcionando. Tem um problema, o campo padrão "Título da postagem", o registro de pesquisa está repetindo várias vezes e no lado do administrador. Veja: imgur.com/a/W4wmXhO
Super Model
10

A resposta de Stefano é ótima, mas falta uma 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' );

Adicione o código acima, atualize-o e ele funcionará sem duplicatas.

Calara Ionut
fonte
7

Isso vai 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
fonte
11
Por favor, indente adequadamente o seu código e inclua uma explicação sobre por que e como isso funcionará .
precisa saber é
Embora eu tenha votado pela primeira vez, percebi que, infelizmente, isso funcionaria em todas as pesquisas dessa mesma forma, podendo quebrar a pesquisa de front-end.
Maciej Paprocki
A adição de uma verificação na if ( $query->query['post_type'] != 'your_custom_post_type' ){ return; }parte superior da função interromperá a execução em outras pesquisas. Observe que a técnica nesta resposta não pesquisa mais o post_title e adicioná-lo novamente não é trivial.
jwinn
Mais um problema - O indicador Resultados da pesquisa para chamadas "<keyword>"get_search_query() que chamam mais get_query_var( 's' ). Como "s" está definido como sequência vazia, os resultados da pesquisa para "" sempre terão um valor vazio entre as aspas. Existe um ajuste nessa solução que contorna isso?
jschrab 29/01
1

Resposta 1: adicione este código no arquivo de função e altere e adicione mais o nome das colunas que você usou no seu tipo de postagem personalizado

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

Resposta 2: Recomendado Use este código no arquivo de funções sem nenhuma alteração

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
fonte
0

Não é uma pesquisa, mas alguns "selecionam" por valor distinto.

No arquivo functions-iworks-posts-filter.zip Você tem um exemplo de como adicionar filtro para postagem regular por alguma meta_key. Eu acho que é fácil converter.

Marcin
fonte
obrigado pela ajuda ... Eu vou olhar para o seu anexo agora. Eu vou deixar você saber os resultados de minha investigação ;-) Stefano
Stefano
Marcin Eu acho que você está se referindo aos filtros como "por data", etc ... mas preciso vincular o campo "pesquisa gratuita" acima. Enfim, acabei de publicar minha solução, talvez ajude Obrigado de qualquer maneira!
Stefano
0

A versão do código aqui em algumas respostas que modifica o parâmetro meta_query da WP_Query da pesquisa em pre_get_posts não estava mais pesquisando o post_title. Adicionando a capacidade de pesquisar o título da postagem, OU os valores meta não podem ser executados diretamente no WP_Query sem modificar o SQL, infelizmente, pois essa pergunta é elaborada a seguir : Usando a meta consulta ('meta_query') com uma consulta de pesquisa ('s')

Combinei algumas das técnicas aqui para obter uma versão de trabalho que evite preg_replaces e muita modificação de SQL (eu gostaria que pudesse ser totalmente evitada). A única desvantagem é que, após uma pesquisa, o texto da legenda na parte superior da página indica "Resultados da pesquisa para ''". Acabei de ocultar isso com CSS para o tipo de postagem personalizada do meu 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');
jwinn
fonte