Niestandardowe podział na strony dla niestandardowych typów postów (według nazw)

10

Mam dwa niestandardowe typy postów, które dotyczą nazwisk osób. Obecnie, podczas przeglądania widoków, po prostu wyświetla je wszystkie alfabetycznie, a paginacja dzieli je według liczb, co nie jest szczególnie pomocne, gdy próbujesz znaleźć konkretną osobę.

W szczególności poproszono mnie o utworzenie linków do stron dla osób, które wyglądają tak:

  • AG
  • HM
  • NQ
  • RQ

Mój problem - nie mogę wymyślić, w jaki sposób mogę wyszukać niestandardowe typy postów za pomocą pierwszej litery jednego pola. Nie jestem więc pewien, jak mogę utworzyć paginację w ten sposób. Czy ktoś ma jakieś sugestie? Dziękuję Ci!

mcleodm3
źródło
Ciekawe ... dam mu szansę, ale nie bardzo szybko. Po kilku dniach mam wolne miejsce. Udostępnij swoje rozwiązanie, jeśli znajdziesz coś wcześniej. Aby rozpocząć filtrowanie post_where, zmodyfikować wyszukiwanie i dokonać podziału na strony, musisz grać z regułami przepisywania, spójrz na query_vars, query_posts i klasę WP_Rewrite. Jestem pewien, że przybijesz to za pomocą tych rzeczy.
Hameedullah Khan
@ mckeodm3 Więc co ??
kaiser

Odpowiedzi:

4

Interesujące pytanie! Rozwiązałem to, rozszerzając WHEREzapytanie o kilka post_title LIKE 'A%' OR post_title LIKE 'B%' ...klauzul. Możesz również użyć wyrażenia regularnego do przeszukiwania zakresu, ale uważam, że baza danych nie będzie wtedy mogła korzystać z indeksu.

To jest sedno rozwiązania: filtr w WHEREklauzuli:

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

Oczywiście nie chcesz zezwalać na losowe wprowadzanie danych zewnętrznych w zapytaniu. Dlatego mam włączony etap dezynfekcji danych wejściowych pre_get_posts, który przekształca dwie zmienne zapytania w prawidłowy zakres. (Jeśli znajdziesz sposób, aby to naprawić, zostaw komentarz, bym mógł to poprawić)

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

Ostatnim krokiem jest stworzenie ładnej reguły przepisywania, abyś mógł przejść do example.com/posts/a-g/lub example.com/posts/azobaczyć wszystkie posty zaczynające się na tę literę (zakres).

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

Możesz zmienić wzór reguły przepisywania, aby zacząć od czegoś innego. Jeśli dotyczy to niestandardowego typu postu, należy dodać &post_type=your_custom_post_typedo podstawienia (drugi ciąg, który zaczyna się od index.php).

Dodanie linków do stronicowania pozostaje dla czytelnika ćwiczeniem :-)

Jan Fabry
źródło
Tylko podpowiedź: like_escape():)
kaiser
3

To pomoże ci zacząć. Nie wiem, jak przerwałbyś zapytanie przy konkretnej literze, a następnie powiedziałeś WP, że jest jeszcze jedna strona z większą ilością liter, ale poniższe zajmuje 99% reszty.

Nie zapomnij opublikować swojego rozwiązania!

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;
kajzer
źródło
To nie jest przetestowane.
kaiser
2

Odpowiedź na przykładzie @ kaiser z niestandardowym typem postu jako funkcją akceptującą parametry początkowe i końcowe alfa. Ten przykład dotyczy oczywiście krótkiej listy elementów, ponieważ nie zawiera stronicowania dodatkowego. Zamieszczam to, abyście mogli włączyć tę koncepcję do swoich, functions.phpjeśli chcesz.

// 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;
    }
}
Tyrus
źródło
1

Oto sposób na zrobienie tego za pomocą filtrów query_varsi 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

Styledev
źródło
0

To nie tyle odpowiedź, ale wskaźnik do kierunku, który należy obrać. Prawdopodobnie będzie to musiało być w 100% niestandardowe - i będzie bardzo zaangażowane. Musisz utworzyć niestandardowe zapytanie SQL (używając klas wpdb), a następnie do paginacji przekażesz te parametry do zapytania niestandardowego. Prawdopodobnie będziesz także musiał stworzyć nowe reguły przepisywania. Niektóre funkcje do sprawdzenia:

add_rewrite_tag( '%byletter%', '([^/]+)');
add_permastruct( 'byletter', 'byletter' . '/%byletter%' );
$wp_rewrite->flush_rules();
paginate_links()
dwenaus
źródło