Ich versuche, eine Kategorievorlage in meinem Thema zu erstellen, die statischen Inhalt anzeigt, wenn sich der Benutzer auf der ersten Seite des Archivs befindet, und dann die Beiträge in der Kategorie auf den folgenden Seiten anzeigt. Ich versuche im Grunde, das Verhalten der Kategorie auf Wired.com nachzubilden, wo http://www.wired.com/category/design eine Zielseite ist, während / category / design / page / 1 eine umgekehrte chronologische Auflistung von Beiträgen wie Ihnen zeigt würde auf einem Kategoriearchiv erwarten.
Der Schlüssel hier ist, dass ich keine Beiträge aus der Kategorie Archiv auf der ersten Seite zeige, also brauche ich die nächste Seite, um mit dem ersten Post zu beginnen. Ich habe zuerst versucht, dies mit offset und manueller Paginierung zu tun, indem ich den Offset der Abfrage auf 0 setze, wenn die ‘paged’ Abfrage var 2 ist. Aber Offset wird ignoriert, wenn es auf Null gesetzt ist, also kann ich den Offset auf setzen 1 und starte mit dem zweiten Beitrag in der Kategorie.
Das habe ich zu functions.php hinzugefügt:
add_action('pre_get_posts', 'category_query_offset', 1 ); function category_query_offset(&$query) { // Before anything else, make sure this is the right query if (!$query->is_category('news')) { return; } // Next, determine how many posts per page $ppp = get_option('posts_per_page'); //Next, detect and handle pagination if ($query->is_paged) { // Manually determine page query offset $page_offset = (($query->query_vars['paged']-1) * $ppp) - $ppp; // Apply adjust page offset $query->set('offset', $page_offset ); } }
Was wäre besser, und was es wie Wired aussieht, ist, die Standardpaginierung zu verwenden, damit die Beiträge auf Seite 1 beginnen, aber eine Seite 0 für den statischen Inhalt einfügen. Hypothetisch scheint dies möglich zu sein, indem man den statischen Inhalt anzeigt, wenn ‘paged’ 0 ist, und die erste Seite von Beiträgen anzeigt, wenn ‘paged’ 1 ist. Das Problem ist, dass ‘paged’ nie 1 ist, weil WordPress ‘paged’ setzt ‘auf Null, wenn der Benutzer die erste Seite anfordert. Das heißt, ‘paged’ ist 0 für beide / category / news / page / 1 und / category / news.
Gibt es eine Möglichkeit zu überprüfen, ob der Benutzer / category / news / page / 1 im Gegensatz zu / category / news angefordert hat? Ist es möglich, alle Beiträge in der Kategorie ab Seite 2 anzuzeigen?
Das ist eine ziemlich interessante Frage ( die ich speziell für Ihre Herangehensweise und Ihre Forschung aufgestockt habe ). Der große Curveball ist hier die erste Seite der Abfrage:
Sie können die Abfrage nicht so einstellen, dass auf der ersten Seite 0
Beiträge zurückgegeben werden
Indem Sie den Seiteninhalt jeder Seite um eine Seite nach oben verschieben, verlieren Sie die letzte Seite, da die Abfrage immer noch nur die gleiche Anzahl an Posts enthält, so dass die Eigenschaft $max_num_pages
weiterhin gleich bleibt
Wir müssen die WP_Query
class irgendwie “tricksen”, um unsere Posts korrekt mit dem Offset einer Seite zurückzugeben, und auch die korrekte Anzahl an Seiten, um nicht die letzte Seite in der Abfrage zu verlieren
Lass uns die folgende Idee betrachten und versuchen, alles in Code zu schreiben. Bevor wir das tun, möchte ich hier jedoch einige Anmerkungen machen
Alles ist ungetestet, also könnte es errorshaft sein. Stellen Sie sicher, dass Sie dies lokal mit aktiviertem Debug testen
Der Code erfordert mindestens PHP 5.3, jede Version unter 5.3 führt zu einem schwerwiegenden Fehler. Beachten Sie, wenn Sie immer noch eine Version unter PHP 5.5 verwenden, sollten Sie bereits vor längerer Zeit aktualisiert haben
Ändern und missbrauchen Sie den Code so, wie Sie es für richtig halten
Was wir brauchen
Damit alles funktioniert, benötigen wir Folgendes:
Die aktuelle Seitennummer wird angezeigt
Die Option posts_per_page
in den posts_per_page
festgelegt
Benutzerdefinierter offset
$found_posts
Eigenschaft $found_posts
der Abfrage, um die Eigenschaft $max_num_pages
zu korrigieren
Paginierung ist WP_Query
kommt eine sehr einfache paar Zeilen Code
if ( empty($q['nopaging']) && !$this->is_singular ) { $page = absint($q['paged']); if ( !$page ) $page = 1; // If 'offset' is provided, it takes precedence over 'paged'. if ( isset( $q['offset'] ) && is_numeric( $q['offset'] ) ) { $q['offset'] = absint( $q['offset'] ); $pgstrt = $q['offset'] . ', '; } else { $pgstrt = absint( ( $page - 1 ) * $q['posts_per_page'] ) . ', '; } $limits = 'LIMIT ' . $pgstrt . $q['posts_per_page']; }
Was grundsätzlich passiert, sobald ein Offset explizit gesetzt ist, wird der paged
Parameter ignoriert. Der erste Parameter der SQL- LIMIT
Klausel wird aus dem Offset neu berechnet und ist die Anzahl der Posts, die in der generierten SQL-Abfrage übersprungen werden.
Wenn Sie offset
auf 0
, schlägt die Offset-Abfrage offensichtlich fehl, was seltsam ist, da die folgende Überprüfung wahr zurückgeben sollte
if ( isset( $q['offset'] ) && is_numeric( $q['offset'] ) )
0
ist eine gültige Zahl und sollte True zurückgeben. Wenn dies bei Ihrer Installation nicht der Fall ist, sollten Sie das Problem beheben
Um auf das vorliegende Problem zurückzukommen, werden wir die gleiche Art von Logik verwenden, um unseren Offset zu berechnen und zu setzen, um Post 1 auf Seite 2 zu erhalten und von dort die Abfrage zu paginieren. Für die erste Seite werden wir nichts ändern, so dass die Posts, die auf Seite 1 sein sollen, immer noch auf der Seite sind, wir müssten sie später nur “verstecken”, damit wir sie nicht auf der Seite anzeigen 1
add_action( 'pre_get_posts', function ( $q ) { if ( !is_admin() // Only target the front end, VERY VERY IMPORTANT && $q->is_main_query() // Only target the main query, VERY VERY IMPORTANT && $q->is_cateory( 'news' ) // Only target the news category ) { $current_page = $q->get( 'paged' ); // Get the current page number // We will only need to run this from page 2 onwards if ( $current_page != 0 ) { // You can also use if ( is_paged() ) { // Get the amount of posts per page $posts_per_page = get_option( 'posts_per_page' ); // Recalculate our offset $offset = ( ( $current_page - 1) * $posts_per_page ) - $posts_per_page; // This should work on page 2 where it returns 0 // Set our offset $q->set( 'offset', $offset ); } } });
Sie sollten die gleichen Beiträge von Seite 1 auf Seite 2 sehen. Wenn dies nicht der Fall ist, gibt entweder is_numeric( 0 )
false zurück ( was nicht sein sollte ) oder Sie haben eine andere pre_get_posts
Aktion, die ebenfalls versucht Setzen Sie einen Offset oder verwenden Sie die posts_*
-Klauselfilter ( genauer gesagt den post_limits
Filter ). Dies wäre etwas, das Sie selbst debuggen müssten.
Das nächste Problem ist die Korrektur der Seitennummerierung, weil Sie, wie ich bereits erwähnt habe, eine kurze Seite haben werden. Dazu müssen wir den Wert von get_option( 'posts_per_page' )
der Anzahl der in der Abfrage gefundenen Posts get_option( 'posts_per_page' )
da wir die Abfrage um diesen Betrag get_option( 'posts_per_page' )
. Auf diese Weise fügen wir der Eigenschaft $max_num_pages
effektiv 1
$max_num_pages
.
add_action( 'found_posts', function ( $found_posts, $q ) { if ( !is_admin() // Only target the front end, VERY VERY IMPORTANT && $q->is_main_query() // Only target the main query, VERY VERY IMPORTANT && $q->is_cateory( 'news' ) // Only target the news category ) { $found_posts = $found_posts + get_option( 'posts_per_page'); } }, 10, 2 );
Dies sollte alles außer der ersten Seite sortieren.
Dies sollte alles in functions.php
gehen
add_action( 'pre_get_posts', function ( $q ) { if ( !is_admin() // Only target the front end, VERY VERY IMPORTANT && $q->is_main_query() // Only target the main query, VERY VERY IMPORTANT && $q->is_cateory( 'news' ) // Only target the news category ) { $current_page = $q->get( 'paged' ); // Get the current page number // We will only need to run this from page 2 onwards if ( $current_page != 0 ) { // You can also use if ( is_paged() ) { // Get the amount of posts per page $posts_per_page = get_option( 'posts_per_page' ); // Recalculate our offset $offset = ( ( $current_page - 1) * $posts_per_page ) - $posts_per_page; // This should work on page 2 where it returns 0 // Set our offset $q->set( 'offset', $offset ); } } }); add_filter( 'found_posts', function ( $found_posts, $q ) { if ( !is_admin() // Only target the front end, VERY VERY IMPORTANT && $q->is_main_query() // Only target the main query, VERY VERY IMPORTANT && $q->is_cateory( 'news' ) // Only target the news category ) { $found_posts = $found_posts + get_option( 'posts_per_page'); } return $found_posts; }, 10, 2 );
Hier gibt es ein paar Optionen:
OPTION 1
Ich würde höchstwahrscheinlich für diese Option gehen. Was Sie hier tun möchten, ist eine category-news.php
zu erstellen ( wenn Sie dies noch nicht getan haben ). Dies ist die Vorlage, die immer dann verwendet wird, wenn die news
angezeigt wird. Diese Vorlage wird sehr einfach sein
Beispiel
< ?php get_header() if ( !is_paged() ) { // This is the first page get_template_part( 'news', 'special' ); } else { // This is not the first page get_template_part( 'news', 'loop' ); } get_sidebar(); get_footer();
Wie Sie sehen können, habe ich zwei Template-Teile, news-special.php
und news-loop.php
. Nun sind die Grundlagen der beiden benutzerdefinierten Vorlagen:
news-special.php
-> Dieser Schablonenteil ist das, was Sie auf der ersten Seite anzeigen möchten. Fügen Sie alle Ihre benutzerdefinierten statischen Informationen hier hinzu. Achten Sie darauf, die Schleife in dieser Vorlage nicht aufzurufen, da sonst die Posts der ersten Seite angezeigt werden.
news-loop.php
-> Dies ist die Vorlage, wo wir die Schleife aufrufen werden. Dieser Abschnitt sieht ungefähr so aus:
global $wp_query; while ( have_posts() ) { the_post(); // Your template tags and markup }
Erstellen Sie eine separate Vorlage mit Ihrem statischen Inhalt und verwenden Sie einfach den category_template
Filter, um diese Vorlage zu verwenden, wenn wir die erste Seite der news
anzeigen. Stellen Sie außerdem sicher, dass Sie die Standardschleife in dieser Vorlage nicht aufrufen. Stellen Sie außerdem sicher, dass Ihre Namenskonvention hier nicht mit Vorlagennamen in der Vorlagenhierarchie kollidiert
Ich hoffe, das ist nützlich. Fühlen Sie sich frei, Kommentare mit Bedenken zu tolerieren
Dank des OP gibt es einen bestimmten Fehler in der WP_Query
class, überprüfen Sie das Trac-Ticket # 34060 . Der Code, den ich gepostet habe, stammt aus WordPress v4.4 und der Bug ist in dieser Version behoben.
Ich ging zurück zum Quellcode von v4.3, wo der Fehler ist, und ich kann bestätigen, dass 0
ignoriert wird, wenn es als Offsetwert eingestellt ist, da der Code einfach überprüft, ob der offset
Parameter empty
. 0
wird in PHP als leer angesehen. Ich bin nicht sicher, ob dieses Verhalten (Bug) nur in v4.3 oder in allen vorherigen Versionen gefunden wird (je nach Ticket ist dieser Fehler in v4.3), aber es gibt einen Patch für diesen Fehler, den Sie überprüfen können draußen im Trac-Ticket. Wie ich schon sagte, dieser Fehler wurde definitiv in v4.4 behoben
Aktualisieren:
add_action('pre_get_posts', 'category_query_offset', 1 ); function category_query_offset($query) { // Before anything else, make sure this is the right query if (!$query->is_category('news')) { return; } // Next, determine paged $ppp = get_option('paged'); } // Next, handle paged if($ppp > 1){ $query->set('paged', $ppp-1); }
Versuchen Sie etwas wie
$paged = ( get_query_var('paged') ) ? get_query_var('paged')-1 : 1; $args = array ( 'paged' => $paged, );