admin管理员组

文章数量:1287838

Let's suppose a Custom Post Type called "Whatever", which will have a root slug set to "whatever".

This makes all posts of type "whatever" be available at site.url/whatever/post-name

I also want a parent page called Whatever to be available at site.url/whatever

To achieve that, I must create the page with said slug and also set the has_archive property to false, when registering the "Whatever" CPT.

So far so good.

Now, I want to have some specific child pages for the page "Whatever", and I want them to be available at site.url/whatever/child-page-name

This last step is not working because when accessing that url, WordPress tries to load a CPT of type "Whatever" with name "child-page-name". And it does not exist.

What I want to do is to prioritize pages during the loading process, so that if a child page of "Whatever" exists with the requested name, it should always be loaded (even if a CPT exists with said name).

I don't know where to start. I thought about having the single-whatever.php file look for a page with the requested post name. But, I don't know what to do with that information if the page exists. Should I redirect? Filter the loaded template? Here is where I am stuck, and any help will be appreciated.

Let's suppose a Custom Post Type called "Whatever", which will have a root slug set to "whatever".

This makes all posts of type "whatever" be available at site.url/whatever/post-name

I also want a parent page called Whatever to be available at site.url/whatever

To achieve that, I must create the page with said slug and also set the has_archive property to false, when registering the "Whatever" CPT.

So far so good.

Now, I want to have some specific child pages for the page "Whatever", and I want them to be available at site.url/whatever/child-page-name

This last step is not working because when accessing that url, WordPress tries to load a CPT of type "Whatever" with name "child-page-name". And it does not exist.

What I want to do is to prioritize pages during the loading process, so that if a child page of "Whatever" exists with the requested name, it should always be loaded (even if a CPT exists with said name).

I don't know where to start. I thought about having the single-whatever.php file look for a page with the requested post name. But, I don't know what to do with that information if the page exists. Should I redirect? Filter the loaded template? Here is where I am stuck, and any help will be appreciated.

Share Improve this question asked Oct 14, 2021 at 14:28 Álvaro FranzÁlvaro Franz 1,1001 gold badge9 silver badges31 bronze badges 2
  • The EASIEST way that you could do this with your set up is create the "child-page-name" as one of your actual post types. – rudtek Commented Oct 15, 2021 at 4:32
  • @rudtek Thanks for the suggestion, but in this case I also need the page to use page templates, which are different than the post-type template. – Álvaro Franz Commented Oct 15, 2021 at 8:07
Add a comment  | 

1 Answer 1

Reset to default 2

I want to have some specific child pages for the page "Whatever", and I want them to be available at site.url/whatever/child-page-name

What I want to do is to prioritize pages during the loading process, so that if a child page of "Whatever" exists with the requested name, it should always be loaded (even if a CPT exists with said name).

If the child pages have to be Pages (posts of the page type), then you can use the parse_request hook to conditionally change the request type, which in your case is from a custom post type request to a standard (child) Page request, which means that is_page() would return true and WordPress would also load the correct template for Pages like page-whatever.php.

Working example, tried & tested on WordPress 5.8.1:

Note: get_page_uri() is used to retrieve the "directory" path of the child Page, so if parent is the parent Page slug and child is the child Page slug, then the path would be parent/child.

add_action( 'parse_request', 'my_parse_request' );
function my_parse_request( $wp ) {
    $post_type = 'whatever'; // set the post type slug
    // and the "whatever" below is the Page slug

    // This code checks if the path of the current request/page URL begins with
    // "whatever/" as in https://example/whatever/child-page-name and also
    // https://example/whatever/child-page-name/page/2 (paginated request).
    // We also check if the post_type var is the post type set above.
    if ( preg_match( '#^whatever/#', $wp->request ) &&
        isset( $wp->query_vars['post_type'], $wp->query_vars['name'] ) &&
        $post_type === $wp->query_vars['post_type']
    ) {
        $posts = get_posts( array(
            'post_type' => 'page',
            'name'      => $wp->query_vars['name'],
        ) );

        // If a (child) Page with the same name/slug exists, we load the Page,
        // regardless the post type post exists or not.
        if ( ! empty( $posts ) ) {
            $wp->query_vars['pagename'] = get_page_uri( $posts[0] );

            unset( $wp->query_vars['post_type'], $wp->query_vars['name'],
                $wp->query_vars[ $post_type ] );
        }
    }
}

本文标签: url rewritingShare root slug for Child Page and Custom Post Type (prioritizing child pages over posts)