$conf, $runtime; function_exists('chdir') AND chdir(APP_PATH); $r = 'mysql' == $conf['cache']['type'] ? website_set('runtime', $runtime) : cache_set('runtime', $runtime); } function runtime_truncate() { global $conf; 'mysql' == $conf['cache']['type'] ? website_set('runtime', '') : cache_delete('runtime'); } register_shutdown_function('runtime_save'); ?>url rewriting - Custom post-type in root directory, blog posts in subdirectory|Programmer puzzle solving
最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

url rewriting - Custom post-type in root directory, blog posts in subdirectory

matteradmin12PV0评论

I have a website with one custom post type as well as a blog.

For the custom post type I would like to have the slug as root, like so

/<title>

And the blog post I would like to display under /blog, like so

/<title>

I've managed to "minimize" the custom post type's urls by using these two functions:

add_filter( 'post_type_link', function($post_link, $post, $leavename) {
    if('custom' == $post->post_type && 'publish' == $post->post_status) {
        $post_link = str_replace( '/' . $post->post_type . '/', '/', $post_link);
        return $post_link;
    }

    return $post_link;

}, 10, 3 );

and

add_action('pre_get_posts', function($query) {
    if ( ! $query->is_main_query() || 3 != count( $query->query ) || ! isset( $query->query['page'] ) ) {
        return;
    }

    if ( ! empty( $query->query['name'] ) ) {
        $query->set( 'post_type', array( 'post', 'custom', 'page' ) );
    }
});

However, I have not managed to move my blog posts to /blog.

I've tried to set the permalink structure to

/blog/%postname%/

and the custom post type's rewrite to

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

However, this does not produce the desired effect (domain/title). Instead, the "custom" slug is now part of the url again. Manually removing it (domain/title) produces a 404.

I have a website with one custom post type as well as a blog.

For the custom post type I would like to have the slug as root, like so

http://domain/<title>

And the blog post I would like to display under /blog, like so

http://domain/blog/<title>

I've managed to "minimize" the custom post type's urls by using these two functions:

add_filter( 'post_type_link', function($post_link, $post, $leavename) {
    if('custom' == $post->post_type && 'publish' == $post->post_status) {
        $post_link = str_replace( '/' . $post->post_type . '/', '/', $post_link);
        return $post_link;
    }

    return $post_link;

}, 10, 3 );

and

add_action('pre_get_posts', function($query) {
    if ( ! $query->is_main_query() || 3 != count( $query->query ) || ! isset( $query->query['page'] ) ) {
        return;
    }

    if ( ! empty( $query->query['name'] ) ) {
        $query->set( 'post_type', array( 'post', 'custom', 'page' ) );
    }
});

However, I have not managed to move my blog posts to /blog.

I've tried to set the permalink structure to

/blog/%postname%/

and the custom post type's rewrite to

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

However, this does not produce the desired effect (domain/title). Instead, the "custom" slug is now part of the url again. Manually removing it (domain/title) produces a 404.

Share Improve this question asked Jan 15, 2019 at 22:05 FSHFSH 133 bronze badges 3
  • Could you explain the conditions you use in pre_get_posts function? Especially the one with 3 != ...? – Krzysiek Dróżdż Commented Jan 15, 2019 at 22:19
  • I actually did not write it myself, but found it somewhere. The 3 != part I don't understand myself. – FSH Commented Jan 15, 2019 at 22:22
  • OK. I think it's very specific for given case... – Krzysiek Dróżdż Commented Jan 15, 2019 at 22:23
Add a comment  | 

1 Answer 1

Reset to default 1

moving blog posts to /blog/ is pretty easy and you can use WordPress settings to do that - no coding needed.

The problem you will have though is that after moving posts, your CPT URL structure will conflict with URL structure of pages - so you'll have to modify your pre_get_posts function.

As for your post_type_link you can simplify it a lot (if it is not hierarchical... is it?):

add_filter( 'post_type_link', function($post_link, $post, $leavename) {
    if ('custom' == $post->post_type && 'publish' == $post->post_status) {
        $post_link = site_url('/') . $post->post_name .'/';
    }

    return $post_link;

}, 10, 3 );

And I also wouldn't use pre_get_posts for selecting proper posts. Using parse_request is a lot easier for this task and it allows you to prevent 404 errors a lot easier.

add_action( 'parse_request', function ( $wp ) {
    if ( ! is_admin() ) {
        if ( array_key_exists('error', $wp->query_vars) && '404' == $wp->query_vars['error'] ) {
            $custom_post = get_page_by_path( $wp->request, OBJECT, 'CUSTOM' );

            if ( $custom_post instanceof WP_Post ) {
                unset( $wp->query_vars['error'] );
                $wp->query_vars['page'] = '';
                $wp->query_vars['CUSTOM'] = $wp->query_vars['name'] = $wp->request;
                $wp->query_vars['post_type'] = 'CUSTOM';
            }            
        }
    }

    return $wp;
} );
Post a comment

comment list (0)

  1. No comments so far