简体   繁体   中英

wordpress sticky post on archive page with pagination

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

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;
}

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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM