Paginação customizada para tipos de postagem customizados (por nomes)

10

Eu tenho dois tipos de postagem personalizados que lidam com os nomes das pessoas. Agora, em visualizações de navegação, ele apenas as lista em ordem alfabética e a paginação as divide por números, o que não é muito útil quando você está tentando encontrar uma pessoa específica.

Especificamente, fui solicitado a criar links de paginação para pessoas assim:

  • A-G
  • H-M
  • N-Q
  • R-Q

Meu problema - não consigo descobrir como posso consultar os tipos de postagem personalizados pela primeira letra de um campo. Então, não tenho certeza de como posso criar a paginação dessa maneira. Alguém tem alguma sugestão? Obrigada!

    
por mcleodm3 30.05.2011 / 17:28

5 respostas

4

Pergunta interessante! Eu resolvi isso expandindo a consulta WHERE com um monte de cláusulas post_title LIKE 'A%' OR post_title LIKE 'B%' ... . Você também pode usar uma expressão regular para fazer uma pesquisa de intervalo, mas acredito que o banco de dados não poderá usar um índice.

Este é o núcleo da solução: um filtro na cláusula WHERE :

add_filter( 'posts_where', 'wpse18703_posts_where', 10, 2 );
function wpse18703_posts_where( $where, &$wp_query )
{
    if ( $letter_range = $wp_query->get( 'wpse18703_range' ) ) {
        global $wpdb;
        $letter_clauses = array();
        foreach ( $letter_range as $letter ) {
            $letter_clauses[] = $wpdb->posts. '.post_title LIKE \'' . $letter . '%\'';
        }
        $where .= ' AND (' . implode( ' OR ', $letter_clauses ) . ') ';
    }
    return $where;
}

É claro que você não quer permitir entrada externa aleatória em sua consulta. É por isso que eu tenho uma etapa de sanitização de entrada em pre_get_posts , que converte duas variáveis de consulta em um intervalo válido. (Se você encontrar uma maneira de quebrar isso, por favor, deixe um comentário para que eu possa corrigi-lo)

add_action( 'pre_get_posts', 'wpse18703_pre_get_posts' );
function wpse18703_pre_get_posts( &$wp_query )
{
    // Sanitize input
    $first_letter = $wp_query->get( 'wpse18725_first_letter' );
    $last_letter = $wp_query->get( 'wpse18725_last_letter' );
    if ( $first_letter || $last_letter ) {
        $first_letter = substr( strtoupper( $first_letter ), 0, 1 );
        $last_letter = substr( strtoupper( $last_letter ), 0, 1 );
        // Make sure the letters are valid
        // If only one letter is valid use only that letter, not a range
        if ( ! ( 'A' <= $first_letter && $first_letter <= 'Z' ) ) {
            $first_letter = $last_letter;
        }
        if ( ! ( 'A' <= $last_letter && $last_letter <= 'Z' ) ) {
            if ( $first_letter == $last_letter ) {
                // None of the letters are valid, don't do a range query
                return;
            }
            $last_letter = $first_letter;
        }
        $wp_query->set( 'posts_per_page', -1 );
        $wp_query->set( 'wpse18703_range', range( $first_letter, $last_letter ) );
    }
}

A etapa final é criar uma regra de reescrita bastante para que você possa ir para example.com/posts/a-g/ ou example.com/posts/a para ver todas as postagens que começam com esta (gama de) letra (s).

add_action( 'init', 'wpse18725_init' );
function wpse18725_init()
{
    add_rewrite_rule( 'posts/(\w)(-(\w))?/?', 'index.php?wpse18725_first_letter=$matches[1]&wpse18725_last_letter=$matches[3]', 'top' );
}

add_filter( 'query_vars', 'wpse18725_query_vars' );
function wpse18725_query_vars( $query_vars )
{
    $query_vars[] = 'wpse18725_first_letter';
    $query_vars[] = 'wpse18725_last_letter';
    return $query_vars;
}

Você pode alterar o padrão de regra de reconfiguração para começar com outra coisa. Se for para um tipo de postagem personalizado, adicione &post_type=your_custom_post_type à substituição (a segunda string, que começa com index.php ).

Adicionar links de paginação é deixado como um exercício para o leitor: -)

    
por Jan Fabry 31.05.2011 / 09:49
3

Isso ajudará você a começar. Eu não sei como você iria quebrar a consulta em uma letra específica e, em seguida, dizer ao WP que há outra página com mais letras, mas a seguinte leva 99% do resto.

Não se esqueça de postar sua solução!

query_posts( array( 'orderby' => 'title' ) );

// Build an alphabet array
foreach( range( 'A', 'G' ) as $letter )
    $alphabet[] = $letter;

foreach( range( 'H', 'M' ) as $letter )
    $alphabet[] = $letter;

foreach( range( 'N', 'Q' ) as $letter )
    $alphabet[] = $letter;

foreach( range( 'R', 'Z' ) as $letter )
    $alphabet[] = $letter;

if ( have_posts() ) 
{
    while ( have_posts() )
    {
        global $wp_query, $post;
        $max_paged = $wp_query->query_vars['max_num_pages'];
        $paged = $wp_query->query_vars['paged'];
        if ( ! $paged )
            $paged = (int) 1;

        the_post();

        $first_title_letter = (string) substr( $post->post_title, 1 );

        if ( in_array( $first_title_letter, $alphabet ) )
        {
            // DO STUFF
        }

        // Pagination
        if ( $paged !== (int) 1 )
        {
            echo 'First: '._wp_link_page( 1 );
            echo 'Prev: '._wp_link_page( $paged - 1 );
        }
        while ( $i = 1; count($alphabet) < $max_paged; i++; )
        {
            echo $i._wp_link_page( $i );
        }
        if ( $paged !== $max_paged )
        {
            echo 'Next: '._wp_link_page( $paged + 1 );
            echo 'Last: '._wp_link_page( $max_paged );
        }
    } // endwhile;
} // endif;
    
por kaiser 30.05.2011 / 20:52
2

Uma resposta usando o exemplo do @ kaiser, com um tipo de postagem personalizado como uma função que aceita parâmetros de início e término de alfa. Este exemplo é obviamente para uma pequena lista de itens, pois não inclui paginação secundária. Estou postando para que você possa incorporar o conceito ao seu functions.php , se quiser.

// Dr Alpha Paging
// Tyrus Christiana, Senior Developer, BFGInteractive.com
// Call like alphaPageDr( "A","d" );
function alphaPageDr( $start, $end ) {
    echo "Alpha Start";
    $loop = new WP_Query( 'post_type=physician&orderby=title&order=asc' );      
    // Build an alphabet array of capitalized letters from params
    foreach ( range( $start, $end ) as $letter )
        $alphabet[] = strtoupper( $letter );    
    if ( $loop->have_posts() ) {
        echo "Has Posts";
        while ( $loop->have_posts() ) : $loop->the_post();              
            // Filter by the first letter of the last name
            $first_last_name_letter = ( string ) substr( get_field( "last_name" ), 0, 1 );
            if ( in_array( $first_last_name_letter, $alphabet ) ) {         
                //Show things
                echo  "<img class='sidebar_main_thumb' src= '" . 
                    get_field( "thumbnail" ) . "' />";
                echo  "<div class='sidesbar_dr_name'>" . 
                    get_field( "salutation" ) . " " . 
                    get_field( 'first_name' ) . " " . 
                    get_field( 'last_name' ) . "</div>";
                echo  "<div class='sidesbar_primary_specialty ' > Primary Specialty : " . 
                    get_field( "primary_specialty" ) . "</div>";                
            }
        endwhile;
    }
}
    
por Tyrus 17.08.2011 / 20:11
1

Aqui está uma maneira de fazer isso usando os filtros query_vars e posts_where :

public  function range_add($aVars) {
    $aVars[] = "range";
    return $aVars;
}
public  function range_where( $where, $args ) {
    if( !is_admin() ) {
        $range = ( isset($args->query_vars['range']) ? $args->query_vars['range'] : false );
        if( $range ) {
            $range = split(',',$range);
            $where .= "AND LEFT(wp_posts.post_title,1) BETWEEN '$range[0]' AND '$range[1]'";
        }
    }
    return $where;
}
add_filter( 'query_vars', array('atk','range_add') );
add_filter( 'posts_where' , array('atk','range_where') );

Souce: enlace

    
por Styledev 17.10.2012 / 13:10
0

Isso não é tanto uma resposta, mas mais uma indicação de uma direção a ser tomada. Isso provavelmente terá que ser 100% personalizado - e estará muito envolvido. Você precisará criar uma consulta sql personalizada (usando as classes wpdb) e, em seguida, para paginação, você passará esses parâmetros para sua consulta personalizada. Você provavelmente precisará também criar novas regras de reescrita para isso também. Algumas funções para analisar:

add_rewrite_tag( '%byletter%', '([^/]+)');
add_permastruct( 'byletter', 'byletter' . '/%byletter%' );
$wp_rewrite->flush_rules();
paginate_links()
    
por dwenaus 30.05.2011 / 19:24