2

I have a CPT that I would like to have the 'root'-permalinks:

So for the page: 'Foo Bar' I would like that to have the URL:

https://example.org/foo-bar

I've found out that I achieve this by registering the CPT with the following line in the args for register_post_type( 'my_CPT', $args );:

'rewrite' => array('slug' => '/', 'with_front' => false)

However... When I add that, then my permalinks for my pages don't work. I would ideally give them these permalinks:

https://example.org/page/some-page

How do I do that?

2

Pages are hardcoded to be the default parsing possibility to any URL (or to say it differently, if nothing else matches, wordpress will try to find a page there).

Therefor it is unwise to put permalink structure with no "prefix", but if you really want it that way, just add a page with a "page" slug and make all other pages its sons. This will work great if you do not have many pages and you will have zero code that hacks at parsing and permalink generation to worry about ;)

| improve this answer | |
  • I don't have that many pages, so that option would be fine. But I'm still getting a 404, whenever I try to access the page (both the parent, with 'page' as it's slug) and the child, which has the URL: https://example.org/page/some-page as you mentioned. – Zeth May 29 '18 at 14:57
  • oh, ok maybe not the greatest idea. Probably wordpress matches everything to your CPT. If that is true, the other way around it is to register a page like CPT under the "page" prefix, maybe even have page related labels and remove the core page items from the menues – Mark Kaplun May 29 '18 at 15:33
  • Hmm... I was hoping for a better solution than that. :-/ – Zeth May 29 '18 at 16:08
1

WordPress uses Rewrite Rules to parse the request. It means that if the request matches one of the rule, it will be parsed using that rule.

The rule for pages is one of the last rule made to catch most of the requests that didn't match any earlier rules. So if you add your CPT without any slug, then pages rule won't be fired up...

One way to fix this is to register CPT with a slug and then change their links and WPs behavior. Here's the code:

function register_mycpt() {
    $arguments = array(
        'label' => 'MyCPT',
        'public' => true,
        'hierarchical' => false,
        ...
        'has_archive' => false,
        'rewrite' => true
    );
    register_post_type('mycpt', $arguments);
}
add_action( 'init', 'register_mycpt' );

Now the URLs for these posts will look like these:

http://example.com/mycpt/{post_name}/

But we can easily change this using post_type_link filter:

function change_mycpt_post_type_link( $url, $post, $leavename ) {
    if ( 'mycpt' == $post->post_type ) {
        $url = site_url('/') . $post->post_name . '/';
    }

    return $url;
}
add_filter( 'post_type_link', 'change_mycpt_post_type_link', 10, 3 );

Now the URLs will be correct, but... They won't work. They will be parsed using rewrite rule for pages and will cause 404 error (since there is no page with such URL). But we can fix that too:

function try_mycpt_before_page_in_parse_request( $wp ) {
    global $wpdb;

    if ( is_admin() ) return;

    if ( array_key_exists( 'name', $wp->query_vars ) ) {
        $post_name = $wp->query_vars['name'];

        $id = $wpdb->get_var( $wpdb->prepare(
            "SELECT ID FROM {$wpdb->posts} WHERE post_type = %s AND post_name = %s ",
            'mycpt', $post_name
        ) );

        if ( $id ) {
            $wp->query_vars['mycpt'] = $post_name;
            $wp->query_vars['post_type'] = 'mycpt';
        }

    }
}
add_action( 'parse_request', 'try_mycpt_before_page_in_parse_request' );

PS. Is it wise to use that code? That's another question. It changes behavior of WP in rather major way, so it can be a little bit tricky. But if there is really a need, you can do this...

Disclaimer: This code will work fine for nonhierarchical CPTs, but you can adapt it to work for hierarchical also...

| improve this answer | |

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.