Esta es una pregunta bastante interesante ( que he votado, especialmente por su enfoque e investigación ). La gran bola curva aquí es la primera página de la consulta:
No puede configurar la consulta para que devuelva 0
publicaciones en la primera página
Al mover el contenido de cada página una página hacia arriba, perderá la última página, ya que la consulta solo tendrá la misma cantidad de publicaciones, por lo que la $max_num_pages
propiedad seguirá siendo la misma.
Tendremos que "engañar" de alguna manera a la WP_Query
clase para que devuelva nuestras publicaciones correctamente con el desplazamiento de una página, y también obtenga el número correcto de páginas para no perder la última página de la consulta
Veamos la siguiente idea e intentemos poner todo en código. Sin embargo, antes de hacerlo, me gustaría plantear algunas notas aquí.
NOTAS IMPORTANTES:
No se ha probado todo, por lo que puede tener errores. Asegúrese de probar esto localmente con la depuración activada
El código requiere al menos PHP 5.3, cualquier versión por debajo de 5.3 causará un error fatal. Tenga en cuenta que si todavía usa alguna versión por debajo de PHP 5.5, ya debería haber actualizado hace mucho tiempo
Modifique y abuse del código como mejor le parezca para satisfacer sus necesidades exactas
LA IDEA DE LA BOMBILLA:
LO QUE NECESITAREMOS
Para que todo funcione, necesitaremos lo siguiente:
El número de página actual que se está viendo
La posts_per_page
opción establecida en la configuración de lectura
Personalizado offset
Modificar la $found_posts
propiedad de la consulta para corregir la $max_num_pages
propiedad.
La paginación se WP_Query
reduce a unas pocas líneas de código muy simples
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'];
}
Lo que sucede básicamente, una vez que se establece explícitamente un desplazamiento, paged
se ignora el parámetro. El primer parámetro de la LIMIT
cláusula SQL se vuelve a calcular a partir del desplazamiento y será el número de publicaciones que se omitirán en la consulta SQL generada.
Según su pregunta, aparentemente cuando se establece offset
en 0
, la consulta de desplazamiento falla, lo cual es extraño, ya que la siguiente comprobación debería devolver verdadero
if ( isset( $q['offset'] ) && is_numeric( $q['offset'] ) )
0
es un número válido y debe devolver verdadero. Si esto no ocurre en su instalación, debe depurar el problema
Para volver al tema en cuestión, utilizaremos el mismo tipo de lógica para calcular y establecer nuestro desplazamiento para obtener la publicación 1 en la página 2 y desde allí paginar la consulta. Para la primera página, no modificaremos nada, por lo que las publicaciones que se supone que están en la página 1 seguirán estando en la página de forma normal, solo tendremos que "ocultarlas" más adelante para que no las visualicemos en la página 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 );
}
}
});
Debería ver las mismas publicaciones de la página 1 en la página 2. Como dije anteriormente, si esto no sucede, is_numeric( 0 )
está devolviendo falso ( que no debería ) o tiene otra pre_get_posts
acción que también está tratando de establecer un desplazamiento o usted están utilizando los posts_*
filtros de cláusula ( más específicamente, el post_limits
filtro ). Esto sería algo que necesitaría depurar usted mismo.
El siguiente problema es corregir la paginación, ya que, como dije anteriormente, tendrá una página corta. Para esto, tendremos que agregar el valor de get_option( 'posts_per_page' )
a la cantidad de publicaciones encontradas en la consulta, ya que estamos compensando la consulta por esa cantidad. Al hacer esto, estamos agregando efectivamente 1
a la $max_num_pages
propiedad.
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 );
Esto debería ordenar todo, excepto la primera página.
TODOS JUNTOS AHORA ( y especialmente para @ialocin - Yellow Submarine )
Todo esto debería entrar en 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 );
OPCIONES DE PRIMERA PÁGINA
Aquí hay algunas opciones:
OPCIÓN 1
Lo más probable es que elija esta opción. Lo que querría hacer aquí es crear un category-news.php
( si aún no lo ha hecho ). Esta será la plantilla que se utilizará cada vez que se vea la news
categoría. Esta plantilla será muy sencilla.
Ejemplo
<?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();
Como puede ver, he incluido dos partes de plantilla, news-special.php
y news-loop.php
. Ahora, los conceptos básicos de las dos plantillas personalizadas son:
news-special.php
-> Esta parte de la plantilla será lo que quieras mostrar en la primera página. Agregue toda su información estática personalizada aquí. Tenga mucho cuidado de no llamar al bucle en esta plantilla ya que esto mostraría las publicaciones de la primera página.
news-loop.php
-> Esta es la plantilla donde invocaremos el bucle. Esta sección se verá así:
global $wp_query;
while ( have_posts() ) {
the_post();
// Your template tags and markup
}
OPCION 2
Cree una plantilla separada con su contenido estático y simplemente use el category_template
filtro para usar esta plantilla cuando veamos la primera página de la news
categoría. Además, asegúrese de no invocar el bucle predeterminado en esta plantilla. Además, asegúrese de que su convención de nomenclatura aquí no choque con los nombres de las plantillas dentro de la jerarquía de plantillas
Espero que esto sea útil. Siéntase libre de dejar comentarios con inquietudes
EDITAR
Gracias al OP, hay un error definitivo en la WP_Query
clase, verifique el boleto de tránsito # 34060 . El código que publiqué es de Wordpress v4.4, y el error se corrigió en esta versión.
Regresé al código fuente de v4.3, donde está el error, y puedo confirmar que 0
se ignora cuando se establece como valor, offset
ya que el código simplemente verifica si el offset
parámetro es empty
. 0
se toma como vacío en PHP. No estoy seguro de si este comportamiento (error) solo se encuentra en v4.3 solo o en todas las versiones anteriores (de acuerdo con el ticket, este error está en v4.3), pero hay un parche para este error que puede verificar fuera en el boleto de trac. Como dije, este error definitivamente se ha solucionado en v4.4
return $found_posts;
después de la instrucción if en la acción found_posts. ¡Gracias!