Paginación personalizada para tipos de correos personalizados (por nombre)

10

Tengo dos tipos de publicaciones personalizadas que tratan con los nombres de las personas. En este momento, en las vistas de navegación, solo las enumera alfabéticamente y la paginación las desglosa en números, lo que no es de mucha ayuda cuando se trata de encontrar una persona específica.

Específicamente, me han pedido que cree enlaces de paginación para personas que se parecen a esto:

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

Mi problema: no puedo entender cómo puedo consultar los tipos de publicaciones personalizadas por la primera letra de un campo. Entonces, no estoy seguro de cómo puedo crear la paginación de esta manera. ¿Alguien tiene alguna sugerencia? ¡Gracias!

    
pregunta mcleodm3 30.05.2011 - 17:28

5 respuestas

4

Pregunta interesante! Lo resolví expandiendo la consulta WHERE con un grupo de cláusulas post_title LIKE 'A%' OR post_title LIKE 'B%' ... . También puede usar una expresión regular para realizar una búsqueda de rango, pero creo que la base de datos no podrá usar un índice en ese momento.

Este es el núcleo de la solución: un filtro en la 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;
}

Por supuesto, no desea permitir entradas externas aleatorias en su consulta. Es por eso que tengo un paso de desinfección de entrada en pre_get_posts , que convierte dos variables de consulta en un rango válido. (Si encuentra una manera de romper esto, por favor deje un comentario para que pueda corregirlo)

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

El paso final es crear una regla de reescritura bonita para que puedas ir a example.com/posts/a-g/ o example.com/posts/a para ver todas las publicaciones que comiencen con 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;
}

Puedes cambiar el patrón de regla de reescritura para comenzar con otra cosa. Si esto es para un tipo de publicación personalizada, asegúrate de agregar &post_type=your_custom_post_type a la sustitución (la segunda cadena, que comienza con index.php ).

La adición de enlaces de paginación se deja como un ejercicio para el lector :-)

    
respondido por el Jan Fabry 31.05.2011 - 09:49
3

Esto te ayudará a comenzar. No sé cómo rompería la consulta en una carta específica y luego le diría a WP que hay otra página con más cartas, pero lo siguiente toma el 99% del resto.

¡No olvides publicar tu solución!

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;
    
respondido por el kaiser 30.05.2011 - 20:52
2

Una respuesta utilizando el ejemplo de @kaiser, con un tipo de publicación personalizada como una función que acepta los parámetros alfa de inicio y fin. Este ejemplo es obviamente para una lista corta de elementos, ya que no incluye la paginación secundaria. Lo estoy publicando para que pueda incorporar el concepto a su functions.php si lo desea.

// 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;
    }
}
    
respondido por el Tyrus 17.08.2011 - 20:11
1

Aquí hay una forma de hacerlo usando los filtros query_vars y 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') );

Fuente: enlace

    
respondido por el Styledev 17.10.2012 - 13:10
0

Esto no es tanto una respuesta, sino más bien un indicador de una dirección a tomar. Esto probablemente tendrá que ser 100% personalizado y será muy complicado. Necesitará crear una consulta SQL personalizada (usando las clases wpdb) y luego, para la paginación, pasará estos parámetros a su consulta personalizada. Es probable que también tengas que crear nuevas reglas de reescritura para esto. Algunas funciones a tener en cuenta:

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

Lea otras preguntas en las etiquetas