Paginação personalizada para tipos de postagem personalizados (por nomes)


10

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

Especificamente, me pediram para criar links de paginação para pessoas parecidas com esta:

  • AG
  • HM
  • NQ
  • RQ

Meu problema - não consigo descobrir como 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? Obrigado!


Interessante .. Vou tentar, mas não muito em breve. Eu tenho uma vaga grátis depois de alguns dias. Compartilhe sua solução se encontrar algo antes disso. Apenas para começar a olhar no filtro posts_where para modificar a pesquisa e fazer a paginação que você precisa para jogar com regras de reescrita, dê uma olhada nas query_vars, query_posts e na classe WP_Rewrite. Tenho certeza que você vai acertar essas coisas.
Hameedullah Khan

@ mckeodm3 Então, o que?
Kaiser

Respostas:


4

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

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

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 deseja permitir entrada externa aleatória em sua consulta. É por isso que tenho uma etapa de higienização de entrada pre_get_posts, que converte duas variáveis ​​de consulta em um intervalo válido. (Se você encontrar uma maneira de quebrar isso, 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 para que você possa acessar example.com/posts/a-g/ou example.com/posts/aver todas as postagens começando com essa (faixa 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 reescrita para começar com outra coisa. Se for para um tipo de postagem personalizado, adicione &post_type=your_custom_post_typea substituição (a segunda sequência, que começa com index.php).

A adição de links de paginação é deixada como um exercício para o leitor :-)


Apenas uma dica: like_escape():)
kaiser

3

Isso ajudará você a começar. Não sei como você interromperia a consulta em uma letra específica e depois diria ao WP que há outra página com mais letras, mas o seguinte ocupa 99% do restante.

Não 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;

Não está testado.
Kaiser

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 alfa. Este exemplo é obviamente para uma pequena lista de itens, pois não inclui paginação secundária. Estou publicando para que você possa incorporar o conceito ao seu, functions.phpse 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;
    }
}

1

Aqui está uma maneira de fazer isso usando os filtros query_varse 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: https://gist.github.com/3904986


0

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

add_rewrite_tag( '%byletter%', '([^/]+)');
add_permastruct( 'byletter', 'byletter' . '/%byletter%' );
$wp_rewrite->flush_rules();
paginate_links()
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.