I have an events page displaying an 'events' custom post type. At the top of the page I have 2 upcoming posts in an upcoming event list and then at the bottom I have 3 past events in a past events list. Posts are displayed in each section based on if an 'event date' custom field is in the past or not. The past events uses WP page navi plugin to paginate the posts. 'posts_per_page' is set at one as a test.
There should be 3 pages that have 1 past post displayed on them, respectively. Unfortunately, the pagination shows 5 pages, the first two have no posts displayed on them, as if the posts from the upcoming posts lists are behaving as ghosts. I have removed the upcoming posts list as a test but this makes no difference.
Does anyone know any reason for this? I have no idea. Thanks.
<?php
$temp_post = $post; // Store the Page the Post
// Get the current date
$current_date = date('M d, Y', time());
$current_date = strtotime( $current_date );
$wp_query= null;
$wp_query = new WP_Query();
$args = array( 'post_type' => 'events','posts_per_page' => 1,'paged' => $paged,'meta_key' => 'event_date', 'orderby' => 'meta_value_num', 'order' => 'DESC');
$wp_query->query( $args );
if ( $wp_query->have_posts() ) :
while ( $wp_query->have_posts() ) : $wp_query->the_post();
// Get the date custom field
$post_date = get_field('event_date');
$post_date = strtotime( $post_date );
// If older than post date, don't show it
if( $current_date > $post_date ): ?>
MY POST CONTENT GOES HERE
<?php endif; // END DATE FILTER ?>
<?php endwhile; //END LOOP ?>
<?php /* Start wp-pagenavi support */ ?>
<?php if(function_exists('wp_pagenavi') ) :
echo '<nav class="pag">'; ?>
<?php wp_pagenavi(); ?>
<?php echo '</nav>'; ?>
<?php else: ?>
<?php twentyeleven_content_nav( 'nav-below' ); ?>
<?php endif; ?><?php /* End wp-pagenavi support */ ?>
<?php endif; ?>
<?php $post = $temp_post; // Reset the Post ?>
It's acting as ghost because you are not showing it. You are showing the navigation in the bottom of page. The query returns 5 page, so navigation would be for 5 page.
But you aren't showing the post, if it doesn't meet this condition
// If older than post date, don't show it
if( $current_date > $post_date ): ?>
That's why those posts are not showing. Remove that condition and you will see that all the posts are showing as it should.
If you want to display pagination this way, you would have to limit the number of returned post from query itself.
Thanks a lot, I managed to work it out with a push in the right direction.
// Get the current date
$current_date = date('Ymd', time());
$wp_query= null;
$wp_query = new WP_Query();
$args = array(
'post_type' => 'events',
'posts_per_page' => 1,
'paged' => $paged,
'orderby' => 'meta_value_num',
'order' => 'DESC',
'meta_key' => 'event_date',
'meta_query' => array(
array(
'key' => 'event_date',
'value' => $current_date,
'compare' => '<',
'type' => 'CHAR'
)
)
);
$wp_query->query( $args );
if ( $wp_query->have_posts() ) :
while ( $wp_query->have_posts() ) : $wp_query->the_post(); ?>
MY POST CONTENT HERE
<?php //endif; // END DATE FILTER ?>
<?php endwhile; //END LOOP ?>
<?php /* Start wp-pagenavi support */ ?>
<?php if(function_exists('wp_pagenavi') ) :
echo '<nav class="pag">'; ?>
<?php wp_pagenavi(); ?>
<?php echo '</nav>'; ?>
<?php endif; ?><?php /* End wp-pagenavi support */ ?>
<?php endif; ?>
Related
Try to achieve this:
I made a ACF (custom field) in my WooCommerce Product and now I try to get this field shown in my template with this code:
<ul class="products">
<?php
$args = array(
'posts_per_page' => 20,
'post_type' => 'product',
'tax_query' => array(
array(
'taxonomy' => 'product_type',
'field' => 'name',
'terms' => 'grouped',
),
),
);
$loop = new WP_Query( $args );
if ( $loop->have_posts() ) {
while ( $loop->have_posts() ) : $loop->the_post();
$linked_with_items = the_field('linked_with_items');
the_title('<strong>', '</strong>'); echo '<br />';
echo $linked_with_items;
endwhile;
} else {
echo __( 'No products found' );
}
wp_reset_postdata();
?>
</ul><!--/.products-->
But whatever I try also with get_field() the field does not show in my template.
Can someone help?
https://www.advancedcustomfields.com/
This is the final code fyi
<?php if( have_rows('catalogue') ): ?>
<?php
while( have_rows('catalogue') ): the_row(); // catalogue is the field
the_sub_field('linked_with_items'); ?>
<?php endwhile; ?>
<?php endif; ?>
You could try with this:
$linked_with_items = get_field('linked_with_items', get_the_ID());
If that doesn't work, just as a test, you could try to simply loop over posts with a foreach
foreach ( $loop->posts as $post ) {
$linked_with_items = get_field('linked_with_items', $post->ID);
}
If none of those work, please make sure that your product actually have that custom field, double check the ACF field settings (rule section), the field slug, and double check your product edit page to see if the fields shows there.
I have a WP_Query which contains data that I want to loop over on the page:
$query_posts_for_board_game = new WP_Query(get_posts(array(
'post_type' => $mm_custom_post_types,
'numberposts' => 20,
'meta_query' => array(
array(
'key' => array('board_game', 'board_games'),
'value' => get_the_ID(),
'compare' => 'LIKE'
)
)
)));
When I var_dump it I can see that it has the data in the query and query_vars properties but when I loop over it using the $query_posts_for_board_game->have_posts() method nothing is output. This code simply prints the else block.
<?php if($query_posts_for_board_game->have_posts()): ?>
<?php while ($query_posts_for_board_game->have_posts()) : $query_posts_for_board_game->the_post(); ?>
<?php get_template_part('template-parts/layouts/content', 'b1' ); ?>
<?php endwhile; ?>
<?php else : ?>
<?php get_template_part('template-parts/layouts/content-none' ); ?>
<?php endif;?>
If I remove the call to WP_Query and just use get_posts I'm able to loop over it with a standard for loop, but then the nested templates can't take advantage of $post like they would with a normal loop:
<?php
// If there are posts
if ($posts_for_board_game) :
// Loop the posts
foreach ($posts_for_board_game as $board_game_post) :
?>
<?php echo $board_game_post->post_title . '<br />'; ?>
<?php
endforeach;
wp_reset_postdata();
?>
<?php endif; ?>
I seem to recall that this is because my custom query isn’t part of “the query”. Is there a way I can override “the query” so that my content can be output? Can I simply move my query further down the page after the other items are output?
I solved it! I'm sort of shocked that it was as easy as this.
I left the WP_Query in place, just like in the first query above. Then in my loop I simply changed the name of the iterator to $post and it started working. Here's the complete code for anyone else who has this question.
$query_posts_for_board_game = new WP_Query(get_posts(array(
'post_type' => $mm_custom_post_types,
'numberposts' => 20,
'meta_query' => array(
array(
'key' => array('board_game', 'board_games'),
'value' => get_the_ID(),
'compare' => 'LIKE'
)
)
)));
$posts_for_board_games = $query_posts_for_board_game->query;
and the output:
<?php if($posts_for_board_games): ?>
<?php foreach ($posts_for_board_games as $post): ?>
<?php get_template_part('template-parts/layouts/content', 'b1' ); ?>
<?php
endforeach;
wp_reset_postdata();
?>
<?php else: ?>
<?php get_template_part('template-parts/layouts/content-none' ); ?>
<?php endif;?>
I'm a little annoyed that I had to use an intermediate variable, to get at the query contents, but I'm fine with this code.
I have this query:
<?php $wp_query = array(
'post__not_in' => array(4269),
'post_type' => 'whatson',
'exclude' => '4269',
'posts_per_page' => 5,
'order' => 'ASC',
'orderby' => 'date',
'post_status' =>array('future','published'));
?>
It's currently showing upcoming posts in order... how can I show the sticky posts at the top, then show the other posts below it?
E.g If two posts have been marked as sticky then they would show at the top, then the other 3 posts will just be the upcoming posts.
I had a similar problem a while back and devised the following solution. This will show you how to output a maximum of five posts, with the sticky ones at the top. You will have to make your own adjustments to the arguments array, but this should point you in the right direction.
It's a matter of determining how many sticky posts were in fact displayed, subtracting that number from 5, then displaying the balance of non-sticky posts.
<?php
function define_loop_args($present_cat, $sticky_toggle = 0 ) {
/*the total number of posts to display*/
$this->maxNum = 5;
$loop_args = array(
'cat' => $present_cat,
);
if ( $sticky_toggle == TRUE ) {
$loop_args['post__in'] = get_option( 'sticky_posts' );
$loop_args['posts_per_page'] = $this->maxNum;
} else {
$loop_args['post__not_in'] = get_option( 'sticky_posts' );
$loop_args['posts_per_page'] = ((int)($this->maxNum) - (int)($this->sticky_count));
}
$this->loop_args = $loop_args;
}
?>
<ul class="no-children">
<?php
/*
* STICKY
*output sticky posts first
*/
$this->define_loop_args( $catID, 1 );
/*
*count the number of sticky posts displayed, in order to calculate how many non-sticky posts to output next
*/
$sticky_count = 0;
// The Query
$the_query = new WP_Query( $this->loop_args );
// The Loop
while ( $the_query->have_posts() ) : $the_query->the_post();
?>
<li><?php the_title(); ?>
<?php
$sticky_count++;
endwhile;
// End The Loop
// Reset Post Data
wp_reset_postdata();
$this->sticky_count = $sticky_count;
/*
* NON-STICKY
*output non-sticky posts next
*/
$this->define_loop_args( $catID );
$the_query = new WP_Query( $this->loop_args );
while ( $the_query->have_posts() ) : $the_query->the_post();
?>
<li><?php the_title(); ?>
<?php
endwhile;
// End The Loop
// Reset Post Data
wp_reset_postdata();
?>
</ul>
you can get it ny multiple loop as follows
<?php
$sticky = get_option( 'sticky_posts' );
$args_ordinary = array(
'post__not_in' => array(4269,$sticky),
'post_type' => 'whatson',
'exclude' => '4269',
'posts_per_page' => 3,
'order' => 'ASC',
'orderby' => 'date',
'post_status' =>array('future','published'));
$args_sticky = array(
'posts_per_page' => -1,
'post__in' => $sticky,
'posts_per_page' => 2,
'post_type' => 'whatson'
);
query_posts($args_sticky);
if (have_posts()): ?>
<?php while (have_posts()) : the_post(); ?>
//sticky post
<?php endwhile; ?>
<?php endif; ?>
// Now Ordinary Posts
query_posts($args_ordinary);
if (have_posts()): ?>
<?php while (have_posts()) : the_post(); ?>
//ordinary post
<?php endwhile; ?>
<?php endif; ?>
I'm using already designed theme for wordpress, and now instead of regular blog posts I would like to display WooCommerce products (which are custom post types I persume).
This is the current query with display loop:
<?php
$args = array(
//'posts_per_page' => '2',
'paged' => get_query_var('paged')
);
$homepage_query = new WP_Query($args);
?>
<?php //query_posts('posts_per_page=4&paged='.get_query_var('paged')); ?>
<?php if ( have_posts() ) : ?>
<?php while ( $homepage_query->have_posts() ) : $homepage_query->the_post(); ?>
<?php if($style == 'blog_style') { ?>
<div id="blog-style" class="post-box">
<?php get_template_part('content', 'blog'); ?>
</div>
<?php } else { ?>
<div class="post-box grid_4 <?php aero_post_box_class(); ?>">
<?php get_template_part('content', ''); ?>
</div>
<?php } ?>
<?php endwhile; ?>
Is there a way to add options to $args so the loop displays WooCommerce products? I'm also using pagination with this loop, which is required on this project, so that's why it's important to use this loop.
You should be able to access products through the loop, setting the post_type arg to product:
<?php
// Setup your custom query
$args = array( 'post_type' => 'product', ... );
$loop = new WP_Query( $args );
while ( $loop->have_posts() ) : $loop->the_post(); ?>
<a href="<?php echo get_permalink( $loop->post->ID ) ?>">
<?php the_title(); ?>
</a>
<?php endwhile; wp_reset_query(); // Remember to reset ?>
This is the proper way to re-create and customize the WooCommerce product loop:
if(!function_exists('wc_get_products')) {
return;
}
$paged = (get_query_var('paged')) ? absint(get_query_var('paged')) : 1; // if your custom loop is on a static front page then check for the query var 'page' instead of 'paged', see https://developer.wordpress.org/reference/classes/wp_query/#pagination-parameters
$ordering = WC()->query->get_catalog_ordering_args();
$ordering['orderby'] = array_shift(explode(' ', $ordering['orderby']));
$ordering['orderby'] = stristr($ordering['orderby'], 'price') ? 'meta_value_num' : $ordering['orderby'];
$products_per_page = apply_filters('loop_shop_per_page', wc_get_default_products_per_row() * wc_get_default_product_rows_per_page());
$products_ids = wc_get_products(array(
'status' => 'publish',
'limit' => $products_per_page,
'page' => $paged,
'paginate' => true,
'return' => 'ids',
'orderby' => $ordering['orderby'],
'order' => $ordering['order'],
));
wc_set_loop_prop('current_page', $paged);
wc_set_loop_prop('is_paginated', wc_string_to_bool(true));
wc_set_loop_prop('page_template', get_page_template_slug());
wc_set_loop_prop('per_page', $products_per_page);
wc_set_loop_prop('total', $products_ids->total);
wc_set_loop_prop('total_pages', $products_ids->max_num_pages);
if($products_ids) {
do_action('woocommerce_before_shop_loop');
woocommerce_product_loop_start();
foreach($products_ids->products as $featured_product) {
$post_object = get_post($featured_product);
setup_postdata($GLOBALS['post'] =& $post_object);
wc_get_template_part('content', 'product');
}
wp_reset_postdata();
woocommerce_product_loop_end();
do_action('woocommerce_after_shop_loop');
} else {
do_action('woocommerce_no_products_found');
}
Using the code above, you would customize the wc_get_products() arguments to get the IDs of the products you want (if you have specific criteria). Once that code is in place, all the features of a native WooCommerce loop will be available to you—pagination, ordering, etc. This method is superior to WP_Query and get_posts() because those two methods can break.
I've written a more detailed blog post about custom WooCommerce loops here: https://cfxdesign.com/create-a-custom-woocommerce-product-loop-the-right-way/
You can Also get Category using thi code
$terms = get_terms('product_cat');
foreach ($terms as $term) {
$term_link = get_term_link( $term, 'product_cat' );
echo '<li>' . $term->name . '</li>';
}
If You want only parent category then
wp_list_categories('taxonomy=product_cat&orderby=order&title_li=&depth=1');
i'm trying to order multiples post types in a page
my solution below is working but the posts are not showing by type after type exactly
<?php $args = array_merge( $wp_query->query,
array( 'post_type' =>array( 'editorial','video','portfolio' ),'posts_per_page=-1','orderby'=>'post_type') );
}
query_posts( $args );
$postType='';
if (have_posts()) : while (have_posts()) : the_post();
$PT = get_post_type( $post->ID );
if($postType != $PT){
$postType = $PT;
echo '<p class="clearfix"><h1>All posts of type : '.$postType.'</h1></p>';
}
?>
<?php
if($postType == 'editorial'){ ?>
<?php echo $postType; ?>
<?php }elseif($postType == 'video'){ ?>
<?php echo $postType; ?>
<?php }elseif($postType == 'portfolio'){
<?php echo $postType; ?>
}
?>
and it output like that:
All posts of type : editorial
editorial
editorial
editorial
All posts of type : video
video
video
All posts of type : editorial //problem
editorial
All posts of type : portfolio
portfolio
portfolio
portfolio
portfolio
thank you in advance
According to the Codex, post_type isn't one of the allowed values for the orderby parameter.
One way around your problem would be to use the posts_orderby filter, something like this:
function order_posts_by_type($original_orderby_statement) {
global $wpdb;
return $wpdb->posts .".post_type ASC";
}
add_filter('posts_orderby', 'order_posts_by_type');
$custom_query = new WP_Query( array(
'post_type' =>array( 'editorial','video','portfolio' ),
'posts_per_page' => '-1',
'orderby'=>'post_type',
'order' => 'ASC'
) );
remove_filter('posts_orderby', 'order_posts_by_type');
FWIW, I'd suggest changing 'posts_per_page=-1' to 'posts_per_page' => -1 to be consistent with your other arguments.