Benutzerdefinierte Paginierung für benutzerdefinierte Beitragstypen (nach Namen)

10

Ich habe zwei benutzerdefinierte Beitragstypen, die sich mit den Namen von Personen befassen. Im Moment werden beim Durchsuchen von Ansichten nur alle alphabetisch aufgelistet, und die Paginierung unterteilt sie nach Zahlen. Dies ist nicht besonders hilfreich, wenn Sie versuchen, eine bestimmte Person zu finden.

Insbesondere wurde ich gebeten, Paginierungslinks für Personen zu erstellen, die so aussehen:

  • AG
  • HM
  • NQ
  • RQ

Mein Problem - Ich kann nicht herausfinden, wie ich die benutzerdefinierten Beitragstypen anhand des Anfangsbuchstabens eines Felds abfragen kann. Dann bin ich mir nicht sicher, wie ich die Paginierung auf diese Weise erstellen kann. Hat jemand irgendwelche Vorschläge? Vielen Dank!

mcleodm3
quelle
Interessant .. Ich werde es versuchen, aber nicht sehr bald. Nach ein paar Tagen habe ich einen freien Platz. Teilen Sie Ihre Lösung mit, wenn Sie zuvor etwas gefunden haben. Schauen Sie sich die Klassen query_vars, query_posts und WP_Rewrite an, um den Filter posts_where zu betrachten, um die Suche zu ändern und die Paginierung durchzuführen, die Sie zum Spielen mit Umschreiberegeln benötigen. Ich bin sicher, Sie werden es mit diesen Dingen nageln.
Hameedullah Khan
@ mckeodm3 Na und?
Kaiser

Antworten:

4

Interessante Frage! Ich habe es gelöst, indem ich die WHEREAbfrage um eine Reihe von post_title LIKE 'A%' OR post_title LIKE 'B%' ...Klauseln erweitert habe. Sie können auch einen regulären Ausdruck verwenden, um eine Bereichssuche durchzuführen, aber ich glaube, dass die Datenbank dann keinen Index verwenden kann.

Dies ist der Kern der Lösung: ein Filter für die WHEREKlausel:

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

Natürlich möchten Sie keine zufälligen externen Eingaben in Ihre Abfrage zulassen. Aus diesem Grund habe ich einen Schritt zur Bereinigung der Eingabe pre_get_posts, der zwei Abfragevariablen in einen gültigen Bereich konvertiert. (Wenn Sie einen Weg finden, dies zu brechen, hinterlassen Sie bitte einen Kommentar, damit ich ihn korrigieren kann.)

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

Der letzte Schritt besteht darin, eine hübsche Umschreiberegel zu erstellen, damit Sie zu allen Posts gehen example.com/posts/a-g/oder example.com/posts/asie sehen können, die mit diesem (Bereich von) Buchstaben beginnen.

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

Sie können das Muster für das Umschreiben von Regeln ändern, um mit etwas anderem zu beginnen. Wenn dies für einen benutzerdefinierten Beitragstyp gilt, müssen Sie &post_type=your_custom_post_typedie Ersetzung hinzufügen (die zweite Zeichenfolge, die mit beginnt index.php).

Das Hinzufügen von Paginierungslinks bleibt dem Leser als Übung :-)

Jan Fabry
quelle
Nur ein Hinweis: like_escape():)
Kaiser
3

Dies wird Ihnen den Einstieg erleichtern. Ich weiß nicht, wie Sie die Abfrage bei einem bestimmten Buchstaben unterbrechen und dann WP mitteilen würden, dass es eine andere Seite mit mehr Buchstaben gibt, aber das Folgende übernimmt 99% des Restes.

Vergessen Sie nicht, Ihre Lösung zu veröffentlichen!

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;
Kaiser
quelle
Es ist nicht getestet.
Kaiser
2

Eine Antwort am Beispiel von @ kaiser mit einem benutzerdefinierten Beitragstyp als Funktion, die Alpha-Start- und Endparameter akzeptiert. Dieses Beispiel ist offensichtlich für eine kurze Liste von Elementen gedacht, da es kein sekundäres Paging enthält. Ich poste es, damit Sie das Konzept in Ihr Konzept integrieren können, functions.phpwenn Sie möchten.

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

Hier ist eine Möglichkeit, dies mithilfe der Filter query_varsund zu tun 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') );

Quelle: https://gist.github.com/3904986

Styledev
quelle
0

Dies ist weniger eine Antwort als vielmehr ein Hinweis auf eine Richtung, die eingeschlagen werden muss. Dies muss wahrscheinlich zu 100% benutzerdefiniert sein - und wird sehr involviert sein. Sie müssen eine benutzerdefinierte SQL-Abfrage erstellen (mithilfe der wpdb-Klassen) und diese Parameter dann zur Paginierung an Ihre benutzerdefinierte Abfrage übergeben. Wahrscheinlich müssen Sie auch dafür neue Umschreiberegeln erstellen. Einige zu untersuchende Funktionen:

add_rewrite_tag( '%byletter%', '([^/]+)');
add_permastruct( 'byletter', 'byletter' . '/%byletter%' );
$wp_rewrite->flush_rules();
paginate_links()
dwenaus
quelle