2

In WordPress, Custom Post Types do not have Sticky functionality as a core feature. It is possible, I'm sure, to create it in certain cases—and I'm working on a project that requires it for archive-{customposttype}.php templates.

I have downloaded and installed a plugin, called Sticky Custom Post Types, which I read in this article could be used along with a little bit of PHP to get_option( 'sticky_posts' ) and reconfigure the array of the query currently being executed.

I know that the plugin works because using if (!is_sticky()) {et cetera} within the loop allows me to alter the output of the sticky (custom post type) posts.

I haven't been able to successfully implement the code from the article—the order doesn't seem to change at all when I place it at the top of my archive-{customposttype}.php template, nor have I been able to make it work through several other attempts. This is probably because I'm not very adept at PHP.

Another thing I tried is creating a new query, specifying that I want only sticky posts (which worked at showing me only sticky posts); trying to store that query in a variable, then calling wp_reset_query(), then creating another query specifying that I don't want sticky posts, trying to store that in a variable, calling wp_reset_query() again; and then merging the two query arrays with array_merge(). Unfortunately my various implementations of this either broke the page, or succeeded at doing absolutely nothing, or only showed the second query's output... and I deleted them out of scorn.

I don't know if I'm going about this in the right way at all, really; and I'm sure plenty of people have confronted and overcome this issue. If anyone has any advice or code snippets to help me implement this feature, it'd be greatly appreciated.

To reiterate for the sake of clarity, I'm attempting to show sticky posts at the top of my archive pages for custom post types.

2
  • CPT's don't support sticky posts nor do archive pages so you have 2 things against you, sometimes it's just better to create a taxonomy.
    – Wyck
    Mar 15, 2013 at 6:28
  • I'm using custom post types because each post type has its own unique set of taxonomies. Mar 15, 2013 at 9:27

2 Answers 2

2

I think the answer to your questions lies on the following webpage.

Its author (Tareq Hasan) faced the same problem as we do and found a solution.

https://tareq.co/2013/01/sticky-posts-in-custom-post-type-archives/

Basically, you need to install the plugin you already have (Sticky Custom Post Types) and add a filter: (I paste the code here so if the page went down, we still have it.)

The plugin is quite old but is very simple in the way it works so it still works perfectly with WordPress 4.2. Same apply to the below code snippet.

Hope it helps you as it helped me.

/**
 * Put sticky posts to top at custom post archives
 * Author: Tareq Hasan
 * Source: http://tareq.wedevs.com/2013/01/sticky-posts-in-custom-post-type-archives/
 * 
 * WordPress doesn't do any processing for sticky posts in custom post type archives.
 * It process sticky posts in homepage only (is_home()). This function processes
 * sticky posts at custom post archive page and puts them to the top of list.
 * 
 * @author Tareq Hasan (http://tareq.weDevs.com)
 *
 * @param array $posts array of queried posts
 * @return array
 */
function wedevs_cpt_sticky_at_top( $posts ) {

    // apply the magic on post archive only
    if ( is_main_query() && is_post_type_archive() ) {
        global $wp_query;

        $sticky_posts = get_option( 'sticky_posts' );
        $num_posts = count( $posts );
        $sticky_offset = 0;

        // loop through the post array and find the sticky post
        for ($i = 0; $i < $num_posts; $i++) {

            // Put sticky posts at the top of the posts array
            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) );
                $sticky_offset++;

                // Remove post from sticky posts array
                $offset = array_search($sticky_post->ID, $sticky_posts);
                unset( $sticky_posts[$offset] );
            }
        }

        // Fetch sticky posts that weren't in the query results
        if ( !empty( $sticky_posts) ) {

            $stickies = get_posts( array(
                'post__in' => $sticky_posts,
                'post_type' => $wp_query->query_vars['post_type'],
                'post_status' => 'publish',
                'nopaging' => true
            ) );

            foreach ( $stickies as $sticky_post ) {
                array_splice( $posts, $sticky_offset, 0, array( $sticky_post ) );
                $sticky_offset++;
            }
        }

    }

    return $posts;
}

add_filter( 'the_posts', 'wedevs_cpt_sticky_at_top' );
0

I'm implementing sticky posts in two custom post types, and I've just had a look at the plugin you mention here. It uses the sticky posts global option which Wordpress uses to identify sticky posts - as far as I can see in the code, it will stick custom post types to the home page. What you need to do in your archive page is:

Get sticky posts

$sticky = get_option( 'sticky_posts' );

Use a query to get only sticky posts for your post type, then output them at the top of the page

$args = array(
    'posts_type' => [your custom post type slug],
    'post__in'  => $sticky
);
$sticky_query = new WP_Query( $args );
while( $sticky_query->have_posts() ) {
    $sticky_query->next_post();
    echo '<li>' . get_the_title( $sticky_query->post->ID ) . '</li>';
}
wp_reset_postdata();

Then modify the main query to exclude sticky posts using

query_posts(array('post__not_in' => $sticky))
1
  • 3
    query_posts is pretty much always a bad idea. Can you rewrite this the use a filter on pre_get_posts?
    – s_ha_dum
    Jun 17, 2013 at 13:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.