So you got a lot of stuff right, and some things wrong, so I’ll go through it line by line
First:
wp_reset_query();
This function cleans up after a query_posts
call, you should never use either of them. Sadly, a lot of tutorial writers use this instead of what they intended to use, wp_reset_postdata
, as it calls that function internally.
To save time, this is what a well formed WP_Query
that cleans up after itself looks like:
$args = array();
$q = new WP_Query( $args );
if ( $q->have_posts() ) { // if posts were found
while( $q->have_posts() { // for each post
$q->the_post(); // set the current post
the_title(); // display its title
the_content(); // display its content
}
// after the loop, reset the current post back to before the loop
wp_reset_postdata();
} else {
// no posts were found
}
Notice that wp_reset_postdata
is called after the while
loop, but inside the if
statement. This way the postdata is only reset if there is work to cleanup.
Second:
Your query arguments are close but not quite right:
$args = array(
'post_type' => 'blogs',
'posts_per_page' => 2,
'tax_query' => array(
array(
'taxonomy' => 'show-blogs',
'field' => $news,
'terms' => $custom_term->slug,
'posts_per_page' => 2,
),
),
);
$loop = new WP_Query( $args );
Notes:
field
identifies what it is you’re searching for. AKA the term withe ID 5, or the term with the slugtest
, etc, it has a limited number of possible values. The default isterm_id
, so you should remove thisterms
is right, but you can make things simpler by passing in the term ID instead, aka'terms' => $custom_term->term_id,
, this might even be a tiny bit faster. Eitherway, always prefer term IDs over term slugs or names, as slugs/names can be edited, but IDs always remain the same- The extra
posts_per_page
doesn’t belong intax_query
Third:
Your code is pulling 2 posts as you wanted, it’s just doing it multiple times. Instead of 1 query that’s misbehaving, it’s multiple queries doing the same thing, but for different terms.
$custom_terms = get_terms('show-blogs');
foreach ( $custom_terms as $custom_term ) {
Lets say that $custom_terms
contains 5
terms. That’s 5 iterations of the loop, and a query for 2 posts in each loop, so 2 posts x 5 iterations = 10 posts.
We can demonstrate this by modifying the start of
$custom_terms = get_terms('show-blogs');
foreach ( $custom_terms as $custom_term ) {
?><h3>Show Blog: <?php echo esc_html( $custom_term->name ); ?></h3><?php
Now we should see each term as a header, followed by 2 posts.
Notable mentions:
- Congratulations on using
esc_url
, escaping is a greatly under-appreciated security measure that can do wonders for securing a site. Escape late escape often - Some CSS grid should make your table layout much simpler/easier to manage
- Avoid putting things like
}
etc on the same line, and indent them, and stick to one style e.g.while () {}
rather thanwhile(): endwhile;
, it avoids an entire class of mistakes and bugs, and it’s much nicer to read and type