How to create ‘Archive Only’ Custom post type in WordPress

How to create ‘Archive Only’ Custom post type in WordPress

Sometimes we need to create ‘Archive Only’ Custom post type with no single view, such as Testimonial, Team, Coupons etc. But there is no direct way to do it in WordPress. However, by using a specific hook, we can do a little bit of tweaking.

Let’s just start by creating a Custom Posts type ‘Team’.

// register custom 'team' post type
add_action('init', function() {
    register_post_type('team',
        array(
          'labels' => array(
            'name'          => __( 'Team Members' ),
            'singular_name' => __( 'Team Member' ),
            'add_new_item'  => __('Add New Team Member'),
            'edit_item'     => __('Edit Member'),
            'new_item'      => __('New Member'),
            'view_item'     => __('View Member')
          ),
          'public' => true,
          'has_archive' => true,
          'publicly_queryable'	=> true,
        )
    );
});

This will create an Acrhive and a Single page for this post. Here the trick is to redirect the single page to the Archive page using the template_redirect hook. You can see as per https://codex.wordpress.org:

This action hook executes just before WordPress determines which template page to load. It is a good hook to use if you need to do a redirect with full knowledge of the content that has been queried.

You need to paste the following code to the functions.php in your theme.

// redirect single posts to the archive page, scrolled to current ID 
add_action( 'template_redirect', function() {
    if ( is_singular('team') ) {
        global $post;
        $redirect_link = get_post_type_archive_link( 'team' )."#team".$post->ID;
        wp_safe_redirect( $redirect_link, 302 );
        exit;
    }
});

This redirection will work for the single ‘team’ page only, as there is a conditional statement is_singular('team'). The $redirect_link retrieves the archive URL of ‘team’ and passes the URL to wp_safe_redirect function. The first parameter wp_safe_redirect() accepts is the redirection URL. The last parameter is the status code. Default value is 302 which is used for temporary redirection. When this URL is hooking through the template_redirect the single page will automatically redirect to the Archive page. You can use whatever URL you like to redirect the page. If you need to redirect to the homepage, use home_url() instead.

We can always use wp_redirect() function, but it does not validate that the URL is a reference to the current host. This means that this function is vulnerable to open redirects if you pass it a URL supplied by the user. For this reason, it is best practice to always use wp_safe_redirect instead, since it will use wp_validate_redirect() to ensure that the URL refers to the current host.

If you do not need pagination for this specific ‘team’ post, you can use the following code.

// turn off pagination for the archive page
add_action('parse_query', function($query) {
    if (is_post_type_archive('team')) {
        $query->set('nopaging', 1);
    }
});

For full reference of action hooks and functions used here, see the following:

Leave a Comment