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

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.com/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. 🙂