Resolve a custom post type name vs. page permalink conflict (same slug)

The question:

I have a custom post type called “visningshus”, and also a Page with that slug. This is as it should (must) be.

Currently, “http://my-site.com/visningshus” lists all posts of that type. I want to show the page that has that permalink slug instead.

How can I make WordPress not make the post type name take precedence, but instead the permalink, and show the Page?

The Solutions:

Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.

Method 1

The easiest would be to just disable the archive page for this CPT:

register_post_type( 'visningshus',
    array(
        [...]
        'has_archive' => false,
        [...]
    )
);

Don’t forget to refresh you permalinks afterwards at “Settings > Permalinks”

Method 2

I’m not high enough reputation to comment on @Carl’s post, but his is the correct answer (at least to this situation of keeping the page slug and custom post type slug the same and not using an archive.php file)

But his answer would give errors with pagination. To avoid pagination errors:

add_rewrite_rule('^visningshus/page/([0-9]+)','index.php?pagename=visningshus&paged=$matches[1]', 'top');

This looks at the pagination, grabs the page number, and then on the flip side forces it to use the page with the matching slug, and then inserts the page variable.

This in addition to 'has_archive' => false, posted above should achieve the desired functionality.

As others stated, be sure to flush the rewrite rules by visiting Settings > Permalinks after making this change.

Hope this helps someone, because I know this stumped me for a really long time.

Method 3

Tjena Henrik!

I think all you need to do is to add a rewrite rule to the WordPress Rewrite rules that have already been created. Add this code snippet to your functions.php of your theme or include it as a separate pugin…

add_action('init', function () {
     add_rewrite_rule('visningshus/?$','index.php?pagename=visningshus', 'top');
     flush_rewrite_rules();
}, 1000);

Method 4

If you registered the post type yourself, you can change the archive status and URL in your theme or plugin.

'has_archive' => true, enables the archive in post-type-permalink. so change that to

'has_archive' => false, will disable the archive.

'has_archive' => 'custom-slug', will enable the archive in custom slug(http://my-site.com/custom-slug/).

If a plugin or your theme register it, you can disable it with the way krafter did. You can also use custom slug for the archive.

register_post_type( 'visningshus',
    array(
        [...]
        'has_archive' => 'custom-slug', 
        [...]
    )
);

If you need both the page and the archive the best way would be to put the archive in a different custom slug.

Method 5

I solved it without solving the conflict.
Create a page with slug visningshus and write whatever you want in it.
Take note on the ID of this page.

Create and customize the archive-custom-post-type.php template in whatever way you like (most likely you will just use a page template) but replace the loop part with

$recent = new WP_Query("page_id=your-page-id");  
while($recent->have_posts()) : $recent->the_post();
    the_content();
endwhile;

Then when you’ll go to http://my-site.com/visningshus youll see the content managed by the page at the correct url.

Let me know it it works.

Method 6

Not allowed to vote, but + for Carls solution, register_post_type should have

'has_archive' => false

Simple. However, when you face pagination problems, take a look at

add_rewrite_rule

Method 7

What Fixed it for me was setting archive as false but also Setting the Hierarchical to false when setting up my custom post type!

Method 8

Here is a general solution to prioritize pagination over custom post types content for ANY custom post type slug.

// prioritize pagination over displaying custom post type content
add_action('init', function() {
  add_rewrite_rule(
    '(.?.+?)/page/?([0-9]{1,})/?$',
    'index.php?pagename=$matches[1]&paged=$matches[2]',
    'top'
  );
});

Besides adding this snippet, you should also make sure that your custom post type has archive = false

and last but not least go to the Permalinks settings page Settings > Permalinks (/wp/wp-admin/options-permalink.php) and save current settings to refresh links structure on the page.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Comment