Questa è una domanda piuttosto interessante ( che ho votato, specialmente per il tuo approccio e ricerca ). La curva grande qui è la prima pagina della query:
Non è possibile impostare la query per restituire 0
post nella prima pagina
Spostando il contenuto della pagina di ogni pagina in alto di una pagina, perderai l'ultima pagina in quanto la query avrà ancora solo la stessa quantità di post, quindi la $max_num_pages
proprietà rimarrà sempre la stessa
Dovremo in qualche modo "ingannare" la WP_Query
classe per restituire i nostri post in modo corretto con l'offset di una pagina e anche ottenere il numero corretto di pagine per non perdere l'ultima pagina nella query
Vediamo la seguente idea e proviamo a mettere tutto nel codice. Prima di farlo, vorrei tuttavia sollevare alcune note qui
NOTE IMPORTANTI:
Tutto non è testato, quindi potrebbe essere difettoso. Assicurati di testarlo localmente con il debug attivato
Il codice richiede almeno PHP 5.3, qualsiasi versione precedente alla 5.3 causerà un errore fatale. Nota, se stai ancora utilizzando una versione inferiore a PHP 5.5, dovresti aver già aggiornato molto tempo fa
Modifica e abusa del codice secondo le tue esigenze
L'IDEA DELLA LAMPADINA:
COSA ABBIAMO BISOGNO
Per far funzionare tutto, avremo bisogno di quanto segue:
Il numero di pagina corrente visualizzato
L' posts_per_page
opzione impostata nelle impostazioni di lettura
costume offset
Modificare la $found_posts
proprietà della query per correggere la $max_num_pages
proprietà
L'impaginazione WP_Query
scende in poche righe di codice molto semplici
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'];
}
Ciò che accade sostanzialmente, una volta impostato esplicitamente un offset, il paged
parametro viene ignorato. Il primo parametro della LIMIT
clausola SQL viene ricalcolato dall'offset e sarà il numero di post da saltare nella query SQL generata.
Dalla tua domanda, apparentemente quando impostato offset
su 0
, la query offset non riesce, il che è strano, poiché il seguente controllo dovrebbe restituire vero
if ( isset( $q['offset'] ) && is_numeric( $q['offset'] ) )
0
è un numero valido e dovrebbe restituire vero. In caso contrario, è necessario eseguire il debug del problema
Per tornare al problema in questione, utilizzeremo lo stesso tipo di logica per calcolare e impostare il nostro offset per ottenere il post 1 a pagina 2 e da lì impaginare la query. Per la prima pagina, non modificheremo nulla, quindi i post che si suppone siano nella pagina 1 saranno ancora nella pagina come al solito, dovremmo solo "nasconderli" in seguito in modo da non visualizzarli sulla pagina 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 );
}
}
});
Dovresti vedere gli stessi post da pagina 1 a pagina 2. Come ho detto in precedenza, se ciò non accade, o is_numeric( 0 )
sta restituendo false ( cosa che non dovrebbe ) o hai un'altra pre_get_posts
azione che sta anche cercando di impostare un offset o tu stanno usando i posts_*
filtri della clausola ( più specificamente, il post_limits
filtro ). Questo sarebbe qualcosa di cui dovresti eseguire il debug da solo.
Il prossimo numero è correggere l'impaginazione, perché come ho già detto in precedenza, sarai una pagina breve. Per questo, dovremo aggiungere il valore get_option( 'posts_per_page' )
alla quantità di post trovati nella query poiché stiamo compensando la query di tale importo. facendo ciò, stiamo effettivamente aggiungendo 1
alla $max_num_pages
proprietà.
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 );
Questo dovrebbe ordinare tutto, tranne la prima pagina.
TUTTI INSIEME ADESSO ( e specialmente per @ialocin - Yellow Submarine )
Questo dovrebbe andare tutto in functions.php
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 );
OPZIONI PRIMA PAGINA
Ci sono alcune opzioni qui:
OPZIONE 1
Molto probabilmente sceglierei questa opzione. Quello che vorresti fare qui è creare un category-news.php
( se non l'hai ancora fatto ). Questo sarà il modello che verrà utilizzato ogni volta che news
viene visualizzata la categoria. Questo modello sarà molto semplice
Esempio
<?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();
Come puoi vedere, ho incluso due parti di modello news-special.php
e news-loop.php
. Ora, le basi dei due modelli personalizzati sono:
news-special.php
-> Questa parte del modello sarà quella che vorresti visualizzare sulla prima pagina. Aggiungi qui tutte le tue informazioni statiche personalizzate. Fai molta attenzione a non chiamare il ciclo in questo modello in quanto ciò visualizzerebbe i post della prima pagina.
news-loop.php
-> Questo è il modello in cui invocheremo il ciclo. Questa sezione sarà simile a questa:
global $wp_query;
while ( have_posts() ) {
the_post();
// Your template tags and markup
}
OPZIONE 2
Crea un modello separato con il tuo contenuto statico e usa semplicemente il category_template
filtro per usare questo modello quando visualizziamo la prima pagina della news
categoria. Inoltre, assicurarsi di non richiamare il ciclo predefinito in questo modello. Inoltre, assicurati che la convenzione di denominazione qui non entri in conflitto con i nomi dei modelli all'interno della gerarchia dei modelli
Spero sia utile. Sentiti libero di lasciare commenti con preoccupazioni
MODIFICARE
Grazie all'OP, c'è un bug definito nella WP_Query
classe, controlla il ticket trac # 34060 . Il codice che ho pubblicato proviene da Wordpress v4.4 e il bug è stato corretto in questa versione.
Sono tornato al codice sorgente di v4.3, dove si trova il bug, e posso confermare che 0
viene ignorato quando impostato come valore su offset
come il codice controlla semplicemente se il offset
parametro è empty
. 0
viene considerato vuoto in PHP. Non sono sicuro se questo comportamento (bug) si trova solo nella v4.3 o in tutte le versioni precedenti (in base al ticket, questo bug è nella v4.3), ma esiste una patch per questo bug che puoi controllare fuori nel biglietto del trac. Come ho detto, questo bug è stato risolto definitivamente in v4.4
return $found_posts;
dopo l'istruzione if nell'azione found_posts. Grazie!