I have category page which is redirecing to archieve.php.
you can see here : https://www.dealfinder.lk/category/dining/
There are two sticky posts at the top.
1) Up to 25% OFF at &Co Pub and Kitchen with COMBANK Cards
2) 20% OFF at Robata – Movenpick Hotel Colombo for all HSBC Credit Cards
My pagination is 10 items per post
Right now, it shows me 12 items per post.
Here is my code :
function yell_category_sticky_posts( $posts, $wp_query ) { global $wp_the_query; // Don't continue if this isn't a category query, we're not in the main query or we're in the admin if ( ! $wp_query->is_category || $wp_query !== $wp_the_query || is_admin() ) return $posts; global $wpdb; $q = $wp_query->query_vars; $page = absint( $q['paged'] ); if ( empty( $page ) ) $page = 1; $post_type = $q['post_type']; $sticky_posts = get_option( 'sticky_posts' ); if ( $wp_query->is_category && $page <= 1 && is_array( $sticky_posts ) && !empty( $sticky_posts ) && ! $q['ignore_sticky_posts'] ) { $num_posts = count( $posts ); $sticky_offset = 0; // Loop over posts and relocate stickies to the front. for ( $i = 0; $i < $num_posts; $i++ ) { if ( in_array( $posts[$i]->ID, $sticky_posts ) ) { $sticky_post = $posts[$i]; // Remove sticky from current position array_splice( $posts, $i, 1 ); // Move to front, after other stickies array_splice( $posts, $sticky_offset, 0, array( $sticky_post ) ); // Increment the sticky offset. The next sticky will be placed at this offset. $sticky_offset++; // Remove post from sticky posts array $offset = array_search( $sticky_post->ID, $sticky_posts ); unset( $sticky_posts[$offset] ); } } // If any posts have been excluded specifically, Ignore those that are sticky. if ( !empty( $sticky_posts ) && !empty( $q['post__not_in'] ) ) $sticky_posts = array_diff( $sticky_posts, $q['post__not_in'] ); // Fetch sticky posts that weren't in the query results if ( !empty( $sticky_posts ) ) { $stickies__in = implode( ',', array_map( 'absint', $sticky_posts )); // honor post type(s) if not set to any $stickies_where = ''; if ( 'any' != $post_type && '' != $post_type ) { if ( is_array( $post_type ) ) $post_types = join( "', '", $post_type ); else $post_types = $post_type; $stickies_where = "AND $wpdb->posts.post_type IN ('" . $post_types . "')"; } $stickies = $wpdb->get_results( "SELECT wp_posts.* FROM $wpdb->posts INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id) WHERE 1=1 AND ( wp_term_relationships.term_taxonomy_id IN (" . get_term( $wp_query->query_vars['cat'], 'category' )->term_taxonomy_id . ") ) AND $wpdb->posts.ID IN ($stickies__in) $stickies_where" ); foreach ( $stickies as $sticky_post ) { // Ignore sticky posts are not published. if ( 'publish' != $sticky_post->post_status ) continue; array_splice( $posts, $sticky_offset, 0, array( $sticky_post ) ); $sticky_offset++; } } } return $posts; } add_filter( 'the_posts', 'yell_category_sticky_posts', 10, 2 );
My Issue:
I want to show 10 posts per page, currently it shows 12 posts per page with sticky post.
This question is for master not for new learner.
Anybody master here? Thanks in advance
2 Answers
Answers 1
As I suggested in the comment, save the 'sticky posts' in meta (assuming is_featured_post
as the 'meta key').
Run these only once to set the meta value for existing posts. You can skip this since you are already saving in the meta.
// set meta value of all posts to 0 $all_posts = get_posts(array('post_type'=>'post','posts_per_page'=>-1)); if( is_array( $all_posts ) ) { foreach( $all_posts as $post ) { update_post_meta( $post->ID, 'is_featured_post', '0' ); } } // set meta value of all sticky posts alone to 1 $sticky_posts = get_option( 'sticky_posts' ); if( is_array( $sticky_posts ) ) { foreach ( $sticky_posts as $sticky_post ) { update_post_meta( $sticky_post, 'is_featured_post', '1' ); } }
The below function will update the new sticky meta is_featured_post
each time a post updated (or new post saved).
function save_sticky_meta( $post_id ) { if ( isset( $_REQUEST['sticky'] ) ) { update_post_meta( $post_id, 'is_featured_post', '1' ); } else { update_post_meta( $post_id, 'is_featured_post', '0' ); } } add_action( 'save_post', 'save_sticky_meta' ); add_action( 'edit_post', 'save_sticky_meta' );
Then use pre_get_posts
action to set the category query. We are ordering by both 'meta' and 'date' descending to show the latest at top.
function include_sticky_posts( $query ) { if ( ! is_admin() && $query->is_main_query() && $query->is_category() ) { $query->set( 'meta_key', 'is_featured_post' ); $query->set( 'sticky_sort', true ); //custom sticky order query $query->set( 'orderby', 'meta_value_num date' ); $query->set( 'order', 'DESC' ); } } add_action( 'pre_get_posts', 'include_sticky_posts' );
If you want to randomize non-sticky posts, change the order using the_posts
filter as below.
add_filter( 'the_posts', 'sticky_posts_sort', 10, 2 ); function sticky_posts_sort( $posts, $query ) { // if custom sort set from category query if ( true !== $query->get( 'sticky_sort' ) ) return $posts; // loop through posts & save sticky & other posts in seperate arrays $sticky_posts = get_option( 'sticky_posts' ); $sticky_array = array(); $posts_array = array(); foreach ( $posts as $p ) { if( in_array( $p->ID, $sticky_posts ) ) $sticky_array[] = $p; else $posts_array[] = $p; } // merge both arrays and randomize non-sticky posts alone if( is_array( $posts_array ) ) shuffle( $posts_array ); if( is_array( $sticky_array ) && is_array( $posts_array ) ) $posts = array_merge( $sticky_array, $posts_array ); elseif( is_array( $sticky_array ) ) $posts = $sticky_array; else $posts = $posts_array; return $posts; }
Answers 2
The below function pushes stickies to the top, you should be able to use this to help in your case.
add_filter('the_posts', 'bump_sticky_posts_to_top'); function bump_sticky_posts_to_top($posts) { $stickies = array(); foreach($posts as $i => $post) { if(is_sticky($post->ID)) { $stickies[] = $post; unset($posts[$i]); } } return array_merge($stickies, $posts); }
0 comments:
Post a Comment