WP_Query com “post_title LIKE 'something%'”?

39

Eu preciso fazer um WP_Query com um LIKE no post_title .

Eu comecei com este WP_Query regular:

$wp_query = new WP_Query( 
    array (
        'post_type'        => 'wp_exposants',
        'posts_per_page'   => '1',
        'post_status'      => 'publish',
        'orderby'          => 'title', 
        'order'            => 'ASC',
        'paged'            => $paged
    )
); 

Mas o que eu realmente quero fazer parece com isso no SQL:

$query = "
        SELECT      *
        FROM        $wpdb->posts
        WHERE       $wpdb->posts.post_title LIKE '$param2%'
        AND         $wpdb->posts.post_type = 'wp_exposants'
        ORDER BY    $wpdb->posts.post_title
";
$wpdb->get_results($query);

A saída imprime os resultados que estou esperando, mas eu uso o <?php while ( $wp_query->have_posts() ) : $wp_query->the_post(); ?> normal para exibir os resultados.
E isso não está funcionando com $wpdb->get_results() .

Como posso alcançar o que descrevi aqui?

    
por Ludo 30.05.2011 / 14:11
fonte

5 respostas

43

Eu resolveria isso com um filtro em WP_Query . Um que detecta uma variável de consulta extra e usa isso como o prefixo do título.

add_filter( 'posts_where', 'wpse18703_posts_where', 10, 2 );
function wpse18703_posts_where( $where, &$wp_query )
{
    global $wpdb;
    if ( $wpse18703_title = $wp_query->get( 'wpse18703_title' ) ) {
        $where .= ' AND ' . $wpdb->posts . '.post_title LIKE \'' . esc_sql( $wpdb->esc_like( $wpse18703_title ) ) . '%\'';
    }
    return $where;
}

Dessa forma, você ainda pode chamar WP_Query , apenas passa o título como o argumento wpse18703_title (ou altera o nome para algo mais curto).

    
por Jan Fabry 30.05.2011 / 16:06
fonte
15

Queria atualizar este código para o qual vocês trabalharam no wordpress 4.0 e acima, já que o esc_sql () está obsoleto na versão 4.0.

function title_filter($where, &$wp_query){
    global $wpdb;

    if($search_term = $wp_query->get( 'search_prod_title' )){
        /*using the esc_like() in here instead of other esc_sql()*/
        $search_term = $wpdb->esc_like($search_term);
        $search_term = ' \'%' . $search_term . '%\'';
        $where .= ' AND ' . $wpdb->posts . '.post_title LIKE '.$search_term;
    }

    return $where;
}

O resto do material é o mesmo.

Além disso, quero salientar que você pode usar a variável s nos argumentos WP_Query para passar termos de pesquisa, que também pesquisarão pelo título do post que eu acredito.

Assim:

$args = array(
    'post_type' => 'post',
    's' => $search_term,
    'post_status' => 'publish',
    'orderby'     => 'title', 
    'order'       => 'ASC'        
);
$wp_query = new WP_Query($args);
    
por Ashan Jay 02.01.2015 / 06:36
fonte
15

Simplificado:

function title_filter( $where, &$wp_query )
{
    global $wpdb;
    if ( $search_term = $wp_query->get( 'search_prod_title' ) ) {
        $where .= ' AND ' . $wpdb->posts . '.post_title LIKE \'%' . esc_sql( like_escape( $search_term ) ) . '%\'';
    }
    return $where;
}

$args = array(
    'post_type' => 'product',
    'posts_per_page' => $page_size,
    'paged' => $page,
    'search_prod_title' => $search_term,
    'post_status' => 'publish',
    'orderby'     => 'title', 
    'order'       => 'ASC'
);

add_filter( 'posts_where', 'title_filter', 10, 2 );
$wp_query = new WP_Query($args);
remove_filter( 'posts_where', 'title_filter', 10, 2 );
return $wp_query;
    
por Rao 19.04.2013 / 15:24
fonte
7

Com base em outras respostas antes de mim, para fornecer flexibilidade na situação em que você deseja pesquisar uma postagem que contenha uma palavra em um campo ME ou no título da postagem, forneço essa opção por meio do argumento "title_filter_relation". Nesta implementação, eu só aceito entradas "OR" ou "AND" com um padrão "AND".

function title_filter($where, &$wp_query){
    global $wpdb;
    if($search_term = $wp_query->get( 'title_filter' )){
        $search_term = $wpdb->esc_like($search_term); //instead of esc_sql()
        $search_term = ' \'%' . $search_term . '%\'';
        $title_filter_relation = (strtoupper($wp_query->get( 'title_filter_relation'))=='OR' ? 'OR' : 'AND');
        $where .= ' '.$title_filter_relation.' ' . $wpdb->posts . '.post_title LIKE '.$search_term;
    }
    return $where;
}

Veja um exemplo do código em ação para um tipo de postagem muito simples "faq", em que a pergunta é o próprio título da postagem:

add_filter('posts_where','title_filter',10,2);
$s1 = new WP_Query( array(
    'post_type' => 'faq',
    'posts_per_page' => -1,
    'title_filter' => $q,
    'title_filter_relation' => 'OR',
    'post_status' => 'publish',
    'orderby'     => 'title', 
    'order'       => 'ASC',
    'meta_query' => array(
        'relation' => 'OR',
        array(
            'key' => 'faq_answer',
            'value' => $q,
            'compare' => 'LIKE'
        )
    )
));
remove_filter('posts_where','title_filter',10,2);
    
por David Choy 29.04.2015 / 00:44
fonte
5

Com algumas soluções vulneráveis postadas aqui, eu uso uma versão simplificada e higienizada.

Primeiro, criamos uma função para o filtro posts_where , que permite exibir apenas postagens que correspondam a condições específicas:

function cc_post_title_filter($where, &$wp_query) {
    global $wpdb;
    if ( $search_term = $wp_query->get( 'cc_search_post_title' ) ) {
        $where .= ' AND ' . $wpdb->posts . '.post_title LIKE \'%' . $wpdb->esc_like( $search_term ) . '%\'';
    }
    return $where;
}

Agora adicionamos cc_search_post_title em nossos argumentos de consulta:

$args = array(
    'cc_search_post_title' => $search_term, // search post title only
    'post_status' => 'publish',
);

E finalmente, envolva o filtro em torno da consulta:

add_filter( 'posts_where', 'cc_post_title_filter', 10, 2 );
$query = new WP_Query($args);
remove_filter( 'posts_where', 'cc_post_title_filter', 10 );

Usando get_posts ()

Certas funções que recuperam postagens não executam filtros, portanto, as funções de filtro posts_where que você anexa não modificarão a consulta. Se você planeja usar get_posts() para consultar suas postagens, você precisa definir suppress_filters para false em sua matriz de argumentos:

$args = array(
    'cc_search_post_title' => $search_term,
    'suppress_filters' => FALSE,
    'post_status' => 'publish',
);

Agora você pode usar get_posts() :

add_filter( 'posts_where', 'cc_post_title_filter', 10, 2 );
$posts = get_posts($args);
remove_filter( 'posts_where', 'cc_post_title_filter', 10 );

E quanto ao parâmetro s ?

O parâmetro s está disponível:

$args = array(
    's' => $search_term,
);

Ao adicionar seu termo de pesquisa no trabalho do parâmetro s e ele pesquisar o título da postagem, ele também pesquisará o conteúdo da postagem.

E sobre o parâmetro title que foi adicionado com o WP 4.4?

Passando um termo de pesquisa para o parâmetro title :

$args = array(
    'title' => $search_term,
);

É sensível a maiúsculas e LIKE , não %LIKE% . Essa pesquisa média de hello não retornará a postagem com o título Hello World ou Hello .

    
por Christine Cooper 19.04.2018 / 14:58
fonte

Tags