I'm trying to get 5 posts of one category and paginate them, but my loop doesn't get some posts. In this case, I put 5 posts to retrieve but the loop only returns 2 and sometimes 3.
Finally, when I'm trying to use pagination it doesn't work.
Here is my code:
<?php
// Protect against arbitrary paged values
$paged = ( get_query_var( 'paged' ) ) ? absint( get_query_var( 'paged' ) ) : 1;
$args = array(
'category__in' => array( 11 ),
'category__not_in' => '',
'posts_per_page' => 5,
'post_type' => 'post',
'post_status'=>'publish',
'paged' => $paged,
);
$the_query = new WP_Query($args);
?>
<?php if ( $the_query->have_posts() ) : ?>
<?php while ( $the_query->have_posts() ) : $the_query->the_post();
$the_query->the_post();
// Post content goes here...
//
echo '
<h3 class="tituliNota">
<a href="'.get_permalink().'" class="noteTitle">
<b>'.the_title( ' ', ' ', false ).'</b></a></h3>';
get_the_category();
wp_reset_postdata();
endwhile; ?>
<div class="pagination">
<?php
echo paginate_links( array(
'format' => 'page/%#%',
'current' => $paged,
'total' => $the_query->max_num_pages,
'mid_size' => 5,
'prev_text' => __('« Prev Page'),
'next_text' => __('Next Page »')
) );
?>
</div>
The main query runs before the template is loaded, and WordPress decides what template to load based on the results of that query.
You say your default posts_per_page is set to 5, and there are 2 or 3 posts in that category, so as far as WordPress knows, there is no page 2. Your custom query that you run in the template with a different posts per page setting is unrelated to the main query.
The solution is to make adjustments to the main query before the template is loaded, via the pre_get_posts action. This would go in your theme's functions.php file
function category_posts_per_page( $query ) {
if ( !is_admin()
&& $query->is_category()
&& $query->is_main_query() ) {
$query->set( 'posts_per_page', 5 );
}
}
add_action( 'pre_get_posts', 'category_posts_per_page' );
Related
I created a blognews.php page (it shows the last news with a monthly archive) with this code to exclude some categories.
$args = array(
'post_type' => 'post',
'post_status' => 'publish',
'category__in' => 54,
'category__not_in' => 3 ,
'order' => 'DESC'
);
$query = new WP_Query($args);
and it works, the articles under this category aren't displayed.
But when I do the same thing to archive.php and I click a month, I see the posts under the excluded category.
I tried this but it doesn't work:
<?php if ( have_posts() ) : ?>
<?php
query_posts( array( 'category__and' => array(54), 'posts_per_page' => 20, 'orderby' => 'title', 'order' => 'DESC' ) );
while ($query->have_posts()):
$query->the_post();
get_template_part( 'template-parts/content', 'excerpt' );
Is there an easy way to exclude more categories from the blognews.php page and the archive? What's wrong with my code? Or show only a specific category it will be good too.
Add this code to the functions.php file
function exclude_category( $query ) {
if ( $query->is_archive() && $query->is_main_query() ) {
$query->set( 'cat', '-3' );
}
}
add_action( 'pre_get_posts', 'exclude_category' );
Here all conditions where is_archive is true:
if ( $this->is_post_type_archive
$this->is_date
$this->is_author
$this->is_category
$this->is_tag
$this->is_tax )
$this->is_archive = true;
I am working with a theme that has pagination on the home page for the blog posts. When I click on pg2 (or any page link) it refreshes but shows pg1 content. Is there something missing from the code below that keeps it from working correctly?
<?php
$makenzie_lite_args = array(
'post_type' => 'post',
'paged' => $paged,
'category_name' => 'blogPost'
);
$makenzie_lite_query = new WP_Query( $makenzie_lite_args );
if ( $makenzie_lite_query->have_posts() ) :
// amount of pages
$makenzie_lite_num_pages = $makenzie_lite_query->max_num_pages;
/* Start the Loop */
while ( $makenzie_lite_query->have_posts() ) : $makenzie_lite_query->the_post();
$makenzie_lite_layout = makenzie_lite_get_theme_mod( 'posts_style_template', 'post-s1' );
get_template_part( 'template-parts/listing/' . $makenzie_lite_layout );
endwhile;
else :
get_template_part( 'template-parts/content', 'none' );
endif;
// reset query
wp_reset_postdata(); ?>
EDIT:
I added this code I found on another SE post:
if ( get_query_var('paged') ) {
$paged = get_query_var('paged');
} elseif ( get_query_var('page') ) {
$paged = get_query_var('page');
} else {
$paged = 1;
}
and it works, but now the page numbers just expand as I click thru the pages. Go to ameliaislander.com to see what I mean.
Use get_query_var like this:
$makenzie_lite_args = array(
'post_type' => 'post',
'paged' => get_query_var( 'paged' ),
'category_name' => 'blogPost'
);
Scenario
I'm trying to understand where I have gone wrong with my loop in regards to using my pagination hook. I'm using the theme Understrap, with Understrap-child, and i've made no edits to the pre-built hook which can be found here.
I've used this hook in the loop listed below, which resides in a page template file. However the pagination hook isn't being output? The rest of the loop however, working perfectly fine.
Here's the kicker, I've used exactly the same structure within my index.php file. and it works completely fine. Which is driving me to believe I may need to declare something, just not sure as to what that may be.
Question
I'm wondering if while using a page template, and new WP_Query(); would I need to declare any globals to get $paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1; to work?
Code in Question
For reference I've included my loop, though I'm pretty sure it's ok.
<div class="bg-light">
<div class="container space-top-3 space-bottom-2">
<div class="row">
<?php
$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
$args = array(
'post_type' => 'post',
'orderby' => 'post_date',
'order' => 'desc',
'perm' => 'readable',
'show_post_views' => true,
'posts_per_page' => 9,
'paged' => $paged
);
$latestArticles = new WP_Query( $args );
if( $latestArticles->have_posts() ):
/* Start the Loop */
while( $latestArticles->have_posts() ) : $latestArticles->the_post();
get_template_part( 'loop-templates/content-search', get_post_format() );
endwhile;
endif;?>
</div>
<div class="row mt-3">
<div class="col-auto">
<!-- The pagination component (currently not being output. not sure why.) -->
<?php understrap_pagination(); ?>
</div>
</div>
<?php wp_reset_query(); ?>
<?php else : ?>
<!-- do nothing -->
<?php endif; ?>
</div>
</div>
Thanks for all help, in advance.
Edit-7/11/19:
Tried passing $latestArticles->max_num_pages to understrap_pagination();as such understrap_pagination($latestArticles->max_num_pages);. - Still no luck. :|
The pagination function relies upon $wp_query->max_num_pages (i.e. the max number of pages for the main query), so the function will not work with custom queries:
function understrap_pagination( $args = array(), $class = 'pagination' ) {
if ( $GLOBALS['wp_query']->max_num_pages <= 1 ) {
return;
}
...
}
And while your approach does work, it's really not a good idea to alter the global $wp_query object because doing so is essentially the same as using query_posts() which is not recommended at all — you can see why so by checking the docs here.
However, if you don't want to edit the pagination function (or create your own), then a less risky workaround to get the pagination works with your custom query, is by temporarily changing the — and only the — $wp_query->max_num_pages:
$orig_max_num_pages = $wp_query->max_num_pages; // backup
// Change it just for the pagination.
// and $latestArticles is your custom WP_Query instance.
$wp_query->max_num_pages = $latestArticles->max_num_pages;
$paged = max( get_query_var( 'paged' ), get_query_var( 'page' ), 1 );
understrap_pagination( [
'current' => $paged,
] );
$wp_query->max_num_pages = $orig_max_num_pages; // restore
Sample Page template based on your original code.
A Better Practice: Copy/Edit the pagination function.
Since you're using a child theme, and that Understrap uses locate_template() to load the file (inc/pagination.php) which defines the pagination function, you can just copy the file to the child theme (your-theme/inc/pagination.php) and edit the function so that it works with custom WP_Query queries. Or since the function is pluggable (i.e. defined with a if ( ! function_exists() ) block), you can just copy the code to your child theme's functions.php file.
You can use this modified function (which works well for me) or use it as a reference to create your own:
function understrap_pagination( $args = array(), $class = 'pagination' ) {
$args = wp_parse_args(
$args,
array(
'mid_size' => 2,
'prev_next' => true,
'prev_text' => __( '«', 'understrap' ),
'next_text' => __( '»', 'understrap' ),
'screen_reader_text' => __( 'Posts navigation', 'understrap' ),
'type' => 'array',
'current' => max( 1, get_query_var( 'paged' ) ),
'total' => $GLOBALS['wp_query']->max_num_pages,
)
);
// Nothing to paginate, so let's bail.
if ( ! $links = paginate_links( $args ) ) {
return;
}
?>
<nav aria-label="<?php echo $args['screen_reader_text']; ?>">
<ul class="pagination">
<?php
foreach ( $links as $key => $link ) {
?>
<li class="page-item <?php echo strpos( $link, 'current' ) ? 'active' : ''; ?>">
<?php echo str_replace( 'page-numbers', 'page-link', $link ); ?>
</li>
<?php
}
?>
</ul>
</nav>
<?php
}
Then in your template, call the function like so:
$paged = max( get_query_var( 'paged' ), get_query_var( 'page' ), 1 );
understrap_pagination( [
'current' => $paged,
'total' => $latestArticles->max_num_pages,
] );
Sample Page template based on your original code.
paged vs page
paged and page are both the number of the current page, however:
paged is used with archive-based requests/URLs such as category archives and search results pages. On these requests, page is not set by default. It should also be noted that paged is used with is_paged().
page is used with singular requests/URLs such as single Post and Page pages. On these requests, paged is not set by default.
And the Codex recommends the following approach to get the proper page number on singular requests/URLs:
if ( get_query_var( 'paged' ) ) { $paged = get_query_var( 'paged' ); }
elseif ( get_query_var( 'page' ) ) { $paged = get_query_var( 'page' ); }
else { $paged = 1; }
Or simpler version: $paged = max( get_query_var( 'paged' ), get_query_var( 'page' ), 1 );
NB: That Codex article refers to static front Page, but the information also applies to any Pages/Posts.
And last but not least… with secondary WP_Query calls (like your $latestArticles = new WP_Query( $args )), you just need to call wp_reset_postdata() and no need to call wp_reset_query(). :)
So, I was able to locate this post here by CSS-Tricks which outlines a method that nukes the current $wp_query variable and replaces it with a new instance of WP_Query();
My loop now works as expected however, I was under the impression that $wp_query is reserved, is that not correct? Is it safe to use this method?
My new loop looks like this;
<div class="bg-light">
<div class="container space-top-3 space-bottom-2">
<div class="row">
<?php
$temp = $wp_query;
$wp_query = null;
$wp_query = new WP_Query();
$args = array(
'post_type' => 'post',
'orderby' => 'post_date',
'order' => 'desc',
'perm' => 'readable',
'show_post_views' => true,
'posts_per_page' => $posts_per_page,
'paged' => $paged
); ?>
<?php $wp_query->query($args); ?>
<?php if ( $wp_query->have_posts() ) : ?>
<?php /* Start the Loop */ ?>
<?php while ( $wp_query->have_posts() ) : $wp_query->the_post(); ?>
<?php get_template_part( 'loop-templates/content-search', get_post_format() ); ?>
<?php endwhile; ?>
</div>
<div class="row mt-3">
<div class="col-auto">
<!-- The pagination component -->
<?php understrap_pagination(); ?>
</div>
</div>
<?php else : ?>
<!-- do nothing -->
<?php endif; ?>
<?php $wp_query = null;
$wp_query = $temp; // Reset ?>
</div>
</div>
If anyone knows of a better approach I'd be interested in hearing it. Many thanks in advance. -B.
I have a custom post type - collection
So then I add pages, inside those pages are shortcode to display woocommerce products that have same taxonomy
So for example on the collection page, I add a new page called "Jeans" and I tick checkboxes "denim", "faded", "worn-out" which are custom taxonomies
So on this page will display products that have those taxonomies
This is working fine currently
Now I display all the pages in "collection"
Jeans (3)
Slacks (5)
Shorts (2)
This is my problem now, I cannot count the number of products inside those pages
$paged = ( get_query_var( 'paged' ) ) ? absint( get_query_var( 'paged' ) ) : 1;
$args = array(
'post_type' => 'collection',
'order' => (isset($_GET['sort']) ? $_GET['sort'] : 'ASC'),
'orderby' => 'name',
'posts_per_page' => 100,
'paged' => $paged
);
$loop = new WP_Query( $args );
if ( $loop->have_posts() ) :
while ( $loop->have_posts() ) : $loop->the_post();
get_template_part( 'content', 'collection' );
echo '<br>';
echo 'Number of products: '.$loop->post_count;
endwhile;
else :
get_template_part( 'no-results', 'archive' );
endif;
I am sorry I am still confused what to ask... :-(
you can use get_term for that.
you should use this code with your taxonomy
$term = get_term( 1, 'category' );
echo 'count: '. $term->count;
I have a page called News (using page template page-newslist.php), which is supposed to display posts from the custom post type also named News. I realize that having both with the same name causes issues, so when registering the custom post type, I have a rewrite to differentiate it from the page:
'rewrite' => array('slug' => 'news-article', 'with_front' => true),
I can get the query working and displaying the posts properly, but after all of the articles and posts I've read, I cannot get the pagination to work. Nothing ever shows up for the pagination.
After no success with using the page template query, I tried the archive-news.php method, where it would automatically display the posts from the custom post type. The pagination does work there. The downside of using this method is that there isn't a 'physical' page to tie it to (which would also have custom fields, ability to be nicely added (not hard-coded) into menus, etc.)
Here is the stripped-down code registering the custom post type:
register_post_type('news', array(
'label' => 'News',
'capability_type' => 'post',
'hierarchical' => false,
'rewrite' => array('slug' => 'news-article', 'with_front' => true),
'query_var' => true,
'has_archive' => true,
));
And then the code for the page template:
$paged = 1;
if ( get_query_var('paged') ) $paged = get_query_var('paged');
if ( get_query_var('page') ) $paged = get_query_var('page');
$args = array(
'post_type' => 'news',
'post_status' => 'publish',
'posts_per_page' => 1,
'paged' => $paged
);
$my_query = null;
$my_query = new WP_Query($args);
if($my_query->have_posts()):
while ($my_query->have_posts()) : $my_query->the_post();
...
endwhile;
endif;
wp_reset_query();
// Attempt method 1
posts_nav_link(' — ', __('« Newer Posts'), __('Older Posts »'));
// Attempt method 2
previous_posts_link('« Newer');
next_posts_link('Older »');
Any ideas what's wrong?
Have a look at next page link page, the example here will help. codex.wordpress.org/Template_Tags/next_posts_link
<?php next_posts_link('Older Entries »', 0); ?>
Wordpress codex example.
<?php
// set the "paged" parameter (use 'page' if the query is on a static front page)
$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
// the query
$the_query = new WP_Query( 'cat=1&paged=' . $paged );
?>
<?php if ( $the_query->have_posts() ) : ?>
<?php
// the loop
while ( $the_query->have_posts() ) : $the_query->the_post();
?>
<?php the_title(); ?>
<?php endwhile; ?>
<?php
// next_posts_link() usage with max_num_pages
next_posts_link( 'Older Entries', $the_query->max_num_pages );
previous_posts_link( 'Newer Entries' );
?>
<?php
// clean up after our query
wp_reset_postdata();
?>
<?php else: ?>
<p><?php _e( 'Sorry, no posts matched your criteria.' ); ?></p>
<?php endif; ?>
Pagination Like : Prev 1 2 3 Next
<?php
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$news= new WP_Query(array(
'post_type'=>'post',
'posts_per_page' => 3,
'paged' => $paged,
));
if($news->have_posts()) :
while($news->have_posts()) : $news->the_post();
the_title();
endwhile;
$total_pages = $news->max_num_pages;
if ($total_pages > 1){
$current_page = max(1, get_query_var('paged'));
echo paginate_links(array(
'base' => get_pagenum_link(1) . '%_%',
'format' => '/page/%#%',
'current' => $current_page,
'total' => $total_pages,
'prev_text' => __('« prev'),
'next_text' => __('next »'),
));
}
?>
<?php else :?>
<h3><?php _e('404 Error: Not Found', ''); ?></h3>
<?php endif; ?>
<?php wp_reset_postdata();?>