最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

How to rewrite the beginning and end of the permalink structure in a custom post type?

programmeradmin4浏览0评论

I've created a custom post type called "dvposts" and cannot get the permalink structure to display exactly as I want.

My regular post/page structure is /%postname%/%post_id%/.

I would like my custom post type structure to be /d/%postname%/%post_id%/, with the /d at the beginning. I would also like /d/ to open archive.php.

By sending certain arguments to register_post_type() I've been able to get

  1. /d/%postname%/ and archive at /d/ with

    'has_archive' => true,
    'rewrite' => array('slug' => 'd'),
    
  2. /%postname%/%post_id%/ and archive at /dvposts/ with

    'has_archive' => true,
    // 'rewrite' => array('slug' => 'd'),
    
  3. /dvposts/%postname%/ and archive at /d/ with

    'has_archive' => 'd',
    // 'rewrite' => array('slug' => 'd'),
    
  4. /d/%postname%/ and archive at /d/ with

    'has_archive' => 'd',
    'rewrite' => array('slug' => 'd'),
    

I can't seem to find any information on keeping the regularly set permalink structure (/%postname%/%post_id%/), but with a static prefix (/d/) that also accesses archive.php.

I would prefer to do this within register_post_type(), but if that's not possible, I'm looking for the simplest solution that taxes performance the least.

I've created a custom post type called "dvposts" and cannot get the permalink structure to display exactly as I want.

My regular post/page structure is /%postname%/%post_id%/.

I would like my custom post type structure to be /d/%postname%/%post_id%/, with the /d at the beginning. I would also like /d/ to open archive.php.

By sending certain arguments to register_post_type() I've been able to get

  1. /d/%postname%/ and archive at /d/ with

    'has_archive' => true,
    'rewrite' => array('slug' => 'd'),
    
  2. /%postname%/%post_id%/ and archive at /dvposts/ with

    'has_archive' => true,
    // 'rewrite' => array('slug' => 'd'),
    
  3. /dvposts/%postname%/ and archive at /d/ with

    'has_archive' => 'd',
    // 'rewrite' => array('slug' => 'd'),
    
  4. /d/%postname%/ and archive at /d/ with

    'has_archive' => 'd',
    'rewrite' => array('slug' => 'd'),
    

I can't seem to find any information on keeping the regularly set permalink structure (/%postname%/%post_id%/), but with a static prefix (/d/) that also accesses archive.php.

I would prefer to do this within register_post_type(), but if that's not possible, I'm looking for the simplest solution that taxes performance the least.

Share Improve this question edited Jun 30, 2020 at 23:52 user38365 asked Jun 23, 2020 at 0:37 user38365user38365 2841 gold badge4 silver badges18 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

I recently wrote an answer to a similar question, so be sure to check it out because you can just use the same code, except you'd use the post type dvposts and not ex_article, and use the structure d/%dvposts%/%post_id%.

But the trick there is quite simple: When you call register_post_type() with rewriting enabled, WordPress always appends the post slug placeholder (e.g. %dvposts% in your case) to the post type's rewrite slug (see example below) and stores the permalink structure for that post type in the $extra_permastructs property of the WP_Rewrite class, so we can use that property to make the permalink structure ends with something else, e.g. the post ID in your case:

// AFTER you registered the post type:
register_post_type( 'dvposts', [ 'rewrite' => [ 'slug' => 'd' ], ... ] );
// I.e. register_post_type( '<post type slug>', [ your CPT args here ] );
// And the above would give us this permalink structure: d/%dvposts%, i.e. d/<post slug>

// .. override the permalink structure:
global $wp_rewrite;
$wp_rewrite->extra_permastructs['dvposts']['struct'] = 'd/%dvposts%/%post_id%';
// I.e. $wp_rewrite->extra_permastructs['<post type slug>']['struct'] = '<your structure>';
// And now we'd have this permalink structure instead: d/%dvposts%/%post_id%, i.e. d/<post slug>/<post ID>

So as you can see, we can completely override the whole permalink structure and not just adding something at the end. And in the future, WordPress might add an API for us so that we don't need to directly access WP_Rewrite::$extra_permastructs (to change just the struct value), but for now, that's the easy way to do it. :)

Additionally, %post_id% is a registered rewrite tag (or placeholder) in WordPress core, so there's no need to call add_rewrite_tag().

Update

Despite %post_id% is a built-in rewrite tag in WordPress core, you actually still need to manually replace it for custom post types, because otherwise, the tag will remain as-is in the permalink URL (e.g. example/d/post-slug/%post_id%).

And you can use the post_type_link hook to replace that tag with the correct post ID:

add_filter( 'post_type_link', function ( $post_link, $post ) {
    if ( $post && 'dvposts' === $post->post_type ) {
        return str_replace( '%post_id%', $post->ID, $post_link );
    }
    return $post_link;
}, 10, 2 );

And as I said in the linked answer, don't forget to flush/regenerate the rewrite rules! Just visit the permalink settings page without having to click on the "save" button. :)

发布评论

评论列表(0)

  1. 暂无评论