Impaginazione personalizzata per tipi di post personalizzati (per nome)


10

Ho due tipi di post personalizzati che si occupano dei nomi delle persone. In questo momento, nelle visualizzazioni di navigazione, li elenca solo in ordine alfabetico e l'impaginazione li suddivide per numeri, il che non è molto utile quando stai cercando di trovare una persona specifica.

In particolare, mi è stato chiesto di creare collegamenti di paginazione per le persone che assomigliano a questo:

  • AG
  • HM
  • NQ
  • RQ

Il mio problema: non riesco a capire come posso interrogare i tipi di posta personalizzati con la prima lettera di un campo. Quindi, non sono sicuro di come posso creare la paginazione in questo modo. Qualcuno ha qualche suggerimento? Grazie!


Interessante .. Ci proverò ma non molto presto. Ho uno slot gratuito dopo un paio di giorni. Condividi la tua soluzione se trovi qualcosa prima. Solo per iniziare guarda il filtro posts_where per modificare la ricerca e per fare l'impaginazione che devi giocare con le regole di riscrittura, dai un'occhiata a query_vars, query_posts e alla classe WP_Rewrite. Sono sicuro che lo inchioderai con queste cose.
Hameedullah Khan,

@ mckeodm3 E allora ??
Kaiser,

Risposte:


4

Domanda interessante! L'ho risolto espandendo la WHEREquery con un mucchio di post_title LIKE 'A%' OR post_title LIKE 'B%' ...clausole. È inoltre possibile utilizzare un'espressione regolare per eseguire una ricerca di intervallo, ma credo che il database non sarà in grado di utilizzare un indice.

Questo è il nocciolo della soluzione: un filtro sulla WHEREclausola:

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

Ovviamente non si desidera consentire input esterni casuali nella query. Questo è il motivo per cui ho un passo di sanificazione dell'input pre_get_postsche converte due variabili di query in un intervallo valido. (Se trovi un modo per risolvere questo problema, lascia un commento in modo che io possa correggerlo)

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

Il passaggio finale è quello di creare una regola di riscrittura piuttosto che tu possa andare example.com/posts/a-g/o example.com/posts/avedere tutti i post che iniziano con questa (gamma di) lettere.

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

È possibile modificare il modello di regole di riscrittura per iniziare con qualcos'altro. Se questo è per un tipo di post personalizzato, assicurati di aggiungere &post_type=your_custom_post_typealla sostituzione (la seconda stringa, che inizia con index.php).

L'aggiunta di link di impaginazione viene lasciata come esercizio per il lettore :-)


Solo un suggerimento: like_escape():)
Kaiser

3

Questo ti aiuterà a iniziare. Non so come interromperesti la query con una lettera specifica e poi dire a WP che c'è un'altra pagina con più lettere, ma quanto segue occupa il 99% del resto.

Non dimenticare di pubblicare la tua soluzione!

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;

Non è testato
Kaiser

2

Una risposta usando l'esempio di @ kaiser, con un tipo di post personalizzato come funzione che accetta i parametri alpha start e end. Questo esempio è ovviamente per un breve elenco di elementi, in quanto non include il paging secondario. Lo sto postando in modo che tu possa incorporare il concetto nel tuo, functions.phpse vuoi.

// 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

Ecco un modo per farlo utilizzando i filtri 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

Questa non è tanto una risposta, ma più un puntatore a una direzione da prendere. Probabilmente questo dovrà essere personalizzato al 100% e sarà molto coinvolto. Dovrai creare una query sql personalizzata (usando le classi wpdb) e quindi per l'impaginazione passerai questi parametri alla tua query personalizzata. Probabilmente dovrai anche creare nuove regole di riscrittura anche per questo. Alcune funzioni da esaminare:

add_rewrite_tag( '%byletter%', '([^/]+)');
add_permastruct( 'byletter', 'byletter' . '/%byletter%' );
$wp_rewrite->flush_rules();
paginate_links()
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.