3

I am having troubles with the archives for a custom post type.

  • I have a WordPress page at /address/
  • I have created dynamic custom posts that are to appear at /address/post#/

When I activate this functionality, the WordPress page at /address/ is replaced with the custom posts archive.

How can I stop this from happening? I want the WordPress page to appear at /address/ instead of the archive.

  • Are you aware of archive-address.php? Can you provide a little context as to why you want to use a page at that address? – Tom J Nowell Aug 11 '16 at 22:18
  • @TomJNowell I would guess it's to use the visual editor on the page or to pull the top of the post type hierarchy into wp_list_pages a bit like the page_for_posts option does. – Andy Macaulay-Brook Aug 11 '16 at 23:07
5

When you register your post type, set the has_archive argument to false. If you change it, don't forget to flush your rewrite rules to see the change.

Now this works fine if, as you asked, you want to show the page and not the archive. What about the situation where you'd like to show the page's content and also the listing of custom posts?

There are two approaches you can use to achieve this.

1 - Use a Page Template

This is the one I see most often around the web. Create a page template and after showing the title and content use a custom loop to show your posts. It does the job, but people seem to get messed up with proper pagination quite often.

2 - Page for Custom Posts

This is my preferred approach. I keep has_archive when I register my post type and I make a normal Page to use with the archive template. The Page's slug matches the Archive slug. By default WP's rewrite rules are ordered so that the Archive trumps the Page.

At the start of my archive-{post_type}.php template I place this:

$queried_object = get_queried_object();

$page_data = get_page_by_path( $queried_object->rewrite['slug'] );

/* no need to check our context, as we know that this 
   code will only run for our CPT archives
*/

if ( !is_single() ) {
    echo apply_filters('the_content', $page_data->post_content);
}

// process the content in the same way that the_content would within a loop

// Now go into your usual archive loop...

If you prefer you could use a page ID or even set up an option for your post type that's equivalent to the built-in Page for Posts.

This way you aren't having to reconstruct the more difficult archive query for yourself.

| improve this answer | |
-1

Thanks everyone for your help.

Andy put me on the right track. I just had to add:

flush_rewrite_rules();

Thanks again!

| improve this answer | |
  • If my answer worked for you then by all means accept it ;-) – Andy Macaulay-Brook Sep 20 '16 at 12:37
  • 1
    You don't want to run flush_rewrite_rules() on every page load, by the way, as it's an expensive function. It only needs running once after rewrite rules have been changed. – Andy Macaulay-Brook Oct 14 '16 at 11:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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