pagination personnalisée pour les types de publication personnalisés (par noms)

10

J'ai deux types de publication personnalisés qui traitent des noms de personnes. Pour le moment, dans les vues de navigation, il les répertorie simplement par ordre alphabétique et la pagination les décompose en chiffres, ce qui n’est pas très utile lorsque vous essayez de trouver une personne spécifique.

Plus précisément, on m'a demandé de créer des liens de pagination pour les personnes ressemblant à ceci:

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

Mon problème - Je ne vois pas comment interroger les types de publication personnalisés par la première lettre d'un champ. Ensuite, je ne sais pas comment faire pour créer la pagination de cette manière. Quelqu'un a-t'il des suggestions? Merci!

    
posée mcleodm3 30.05.2011 - 17:28

5 réponses

4

Question intéressante! Je l'ai résolu en développant la requête WHERE avec un ensemble de clauses post_title LIKE 'A%' OR post_title LIKE 'B%' ... . Vous pouvez également utiliser une expression régulière pour effectuer une recherche par plage, mais je pense que la base de données ne pourra alors pas utiliser d'index.

C’est le cœur de la solution: un filtre sur la clause 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;
}

Bien entendu, vous ne souhaitez pas autoriser la saisie externe aléatoire dans votre requête. C'est pourquoi j'ai une étape de désinfection d'entrée sur pre_get_posts , qui convertit deux variables de requête en une plage valide. (Si vous trouvez un moyen de résoudre ce problème, merci de laisser un commentaire afin que je puisse le corriger)

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

La dernière étape consiste à créer une jolie règle de réécriture afin que vous puissiez accéder à example.com/posts/a-g/ ou example.com/posts/a pour voir toutes les publications commençant par cette (série de) lettre (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;
}

Vous pouvez modifier le modèle de règle de réécriture pour commencer par autre chose. S'il s'agit d'un type de publication personnalisé, veillez à ajouter &post_type=your_custom_post_type à la substitution (la deuxième chaîne, qui commence par index.php ).

L'ajout de liens de pagination reste un exercice pour le lecteur: -)

    
réponse donnée Jan Fabry 31.05.2011 - 09:49
3

Cela vous aidera à démarrer. Je ne sais pas comment vous pourriez casser la requête à une lettre spécifique, puis dire à WP qu'il existe une autre page avec plus de lettres, mais la suivante prend 99% du reste.

N'oubliez pas de publier votre solution!

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;
    
réponse donnée kaiser 30.05.2011 - 20:52
2

Une réponse utilisant l'exemple de @ kaiser, avec un type de publication personnalisé en tant que fonction acceptant les paramètres de début et de fin alpha. Cet exemple concerne évidemment une courte liste d'éléments, car il n'inclut pas la pagination secondaire. Je le publie pour que vous puissiez incorporer le concept dans votre functions.php si vous le souhaitez.

// 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;
    }
}
    
réponse donnée Tyrus 17.08.2011 - 20:11
1

Voici un moyen de le faire en utilisant les filtres query_vars et 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') );

Source: enlace

    
réponse donnée Styledev 17.10.2012 - 13:10
0

Ce n’est pas vraiment une réponse, mais plutôt un pointeur sur une direction à prendre. Cela devra probablement être 100% personnalisé - et sera très impliqué. Vous devez créer une requête SQL personnalisée (à l'aide des classes wpdb), puis, pour la pagination, transmettre ces paramètres à votre requête personnalisée. Vous devrez probablement aussi créer de nouvelles règles de réécriture pour cela. Quelques fonctions à examiner:

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

Lire d'autres questions sur les étiquettes