Essa é uma pergunta bastante interessante ( que eu votei, especialmente por sua abordagem e pesquisa ). A grande curva aqui é a primeira página da consulta:
Você não pode definir a consulta para retornar 0
postagens na primeira página
Ao mover o conteúdo da página de uma página para outra em uma página, você perderá a última página, pois a consulta ainda terá apenas a mesma quantidade de postagens, para que a $max_num_pages
propriedade permaneça a mesma
De alguma forma, precisaremos "enganar" a WP_Query
classe para retornar nossas postagens corretamente com o deslocamento de uma página e também obter o número correto de páginas para não perder a última página na consulta
Vamos analisar a ideia a seguir e tentar colocar tudo em código. Antes de fazermos, gostaria de fazer algumas anotações aqui
ANOTAÇÕES IMPORTANTES:
Tudo não foi testado, portanto pode ser um bug. Certifique-se de testar isso localmente com a depuração ativada
O código requer pelo menos PHP 5.3, qualquer versão abaixo de 5.3 causará um erro fatal. Observe que, se ainda estiver usando alguma versão abaixo do PHP 5.5, você já deve ter atualizado há muito tempo
Modifique e abuse do código como achar melhor para atender às suas necessidades exatas
A IDEIA DO LÂMPADA:
O QUE NÓS PRECISAMOS
Para que tudo funcione, precisamos do seguinte:
O número da página atual sendo visualizada
A posts_per_page
opção definida nas configurações de leitura
personalizadas offset
Modifique a $found_posts
propriedade da consulta para corrigir a $max_num_pages
propriedade
Paginação se WP_Query
resume a algumas linhas de código muito 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'];
}
O que basicamente acontece, quando um deslocamento é definido explicitamente, o paged
parâmetro é ignorado. O primeiro parâmetro da LIMIT
cláusula SQL é recalculado do deslocamento e será o número de postagens a serem ignoradas na consulta SQL gerada.
Da sua pergunta, aparentemente ao definir offset
como 0
, a consulta de deslocamento falha, o que é estranho, pois a verificação a seguir deve retornar true
if ( isset( $q['offset'] ) && is_numeric( $q['offset'] ) )
0
é um número válido e deve retornar verdadeiro. Se isso não ocorrer na sua instalação, você deve depurar o problema
Para voltar ao problema em questão, usaremos o mesmo tipo de lógica para calcular e definir nosso deslocamento para obter a postagem 1 na página 2 e a partir daí paginar a consulta. Para a primeira página, não alteraremos nada; portanto, as postagens que deveriam estar na página 1 ainda estarão na página normalmente, apenas precisaríamos "ocultá-las" mais tarde para não exibi-las na página 1 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 );
}
}
});
Você deve ver as mesmas postagens da página 1 na página 2. Como afirmei anteriormente, se isso não acontecer, is_numeric( 0 )
está retornando false (o que não deveria ) ou você tem outra pre_get_posts
ação que também está tentando definir um deslocamento ou você estão usando os posts_*
filtros de cláusula ( mais especificamente, o post_limits
filtro ). Isso seria algo que você precisaria depurar sozinho.
A próxima questão é corrigir a paginação, porque, como afirmei anteriormente, você terá uma página curta. Para isso, precisaremos adicionar o valor da get_option( 'posts_per_page' )
quantidade de postagens encontradas na consulta, pois estamos compensando a consulta por essa quantidade. ao fazer isso, estamos adicionando efetivamente 1
à $max_num_pages
propriedade.
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 );
Isso deve classificar tudo, exceto a primeira página.
TODOS JUNTOS AGORA ( e especialmente para @ialocin - Submarino Amarelo )
Tudo isso deve entrar em 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 );
OPÇÕES DA PRIMEIRA PÁGINA
Existem algumas opções aqui:
OPÇÃO 1
Eu provavelmente iria por esta opção. O que você gostaria de fazer aqui é criar um category-news.php
( se ainda não o fez ). Este será o modelo que será usado sempre que a news
categoria for exibida. Este modelo será muito simples
Exemplo
<?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 você pode ver, incluí duas partes do modelo news-special.php
e news-loop.php
. Agora, o básico dos dois modelos personalizados são:
news-special.php
-> Esta parte do modelo será o que você deseja exibir na primeira página. Adicione todas as suas informações estáticas personalizadas aqui. Tenha muito cuidado para não chamar o loop neste modelo, pois isso exibirá as postagens da primeira página.
news-loop.php
-> Este é o modelo em que chamaremos o loop. Esta seção será mais ou menos assim:
global $wp_query;
while ( have_posts() ) {
the_post();
// Your template tags and markup
}
OPÇÃO 2
Crie um modelo separado com seu conteúdo estático e simplesmente use o category_template
filtro para usá-lo quando visualizarmos a primeira página da news
categoria. Além disso, certifique-se de não chamar o loop padrão neste modelo. Além disso, verifique se a sua convenção de nomenclatura aqui não colide com nomes de modelos na hierarquia de modelos
Espero que isso seja útil. Sinta-se livre para deixar comentários com preocupações
EDITAR
Graças ao OP, há um erro definido na WP_Query
classe, verifique o bilhete trac # 34060 . O código que publiquei é do Wordpress v4.4, e o bug foi corrigido nesta versão.
Voltei ao código fonte da v4.3, onde está o erro, e posso confirmar que 0
é ignorado quando definido como valor, offset
pois o código simplesmente verifica se o offset
parâmetro está empty
. 0
é considerado vazio no PHP. Não tenho certeza se esse comportamento (bug) é encontrado apenas na v4.3 ou em todas as versões anteriores (de acordo com o ticket, esse bug está na v4.3), mas há um patch para esse bug que você pode verificar no bilhete trac. Como eu disse, esse bug foi definitivamente corrigido na v4.4
return $found_posts;
após a instrução if na ação found_posts. Obrigado!