自定义文章类型(CPT)子文章URL重写规则技术咨询
Alright, let's get that clunky, SEO-unfriendly URL structure for your custom post type (CPT) sorted out. You’ve got two solid SEO-friendly options to choose from, and I’ll walk you through implementing each one step by step—since you’re already using the post_type_link filter, we’ll build on that.
This format ties your single posts directly to your CPT’s archive page, making the hierarchy clear to both users and search engines.
Update the
post_type_linkfilter to generate the new URL structure:
Replace your existing filter (or add this if you need to adjust it) with this code snippet (add it to your theme’sfunctions.phpfile or a custom plugin):function custom_cpt_post_link( $post_link, $post ) { if ( 'my-cpt-name' === $post->post_type && 'publish' === $post->post_status ) { // Build the URL using the CPT slug + post slug $post_link = home_url( '/' . $post->post_type . '/' . $post->post_name . '/' ); } return $post_link; } add_filter( 'post_type_link', 'custom_cpt_post_link', 10, 2 );Make sure to replace
my-cpt-namewith your actual CPT’s slug.Add a rewrite rule so WordPress can understand the new URL:
Add this code right after the filter above:function custom_cpt_rewrite_rules() { // Map /my-cpt-name/{post-slug}/ to the single CPT post add_rewrite_rule( '^my-cpt-name/([^/]+)/?$', 'index.php?post_type=my-cpt-name&name=$matches[1]', 'top' ); } add_action( 'init', 'custom_cpt_rewrite_rules' );Flush WordPress rewrite rules:
Go to your WordPress admin → Settings → Permalinks. You don’t need to change any settings—just click the Save Changes button. This tells WordPress to pick up the new rewrite rule.
This format adds a clear, descriptive subdirectory (like news) between the CPT archive and your post slug, which can be helpful if you want to further categorize content.
Update the
post_type_linkfilter:
Use this snippet instead of the one from Option 1:function custom_cpt_post_link_with_subdir( $post_link, $post ) { if ( 'my-cpt-name' === $post->post_type && 'publish' === $post->post_status ) { // Add the "news" subdirectory to the URL structure $post_link = home_url( '/' . $post->post_type . '/news/' . $post->post_name . '/' ); } return $post_link; } add_filter( 'post_type_link', 'custom_cpt_post_link_with_subdir', 10, 2 );Again, replace
my-cpt-namewith your CPT’s slug, and feel free to changenewsto whatever subdirectory name makes sense for your content.Add the matching rewrite rule:
function custom_cpt_rewrite_rules_with_subdir() { add_rewrite_rule( '^my-cpt-name/news/([^/]+)/?$', 'index.php?post_type=my-cpt-name&name=$matches[1]', 'top' ); } add_action( 'init', 'custom_cpt_rewrite_rules_with_subdir' );Flush rewrite rules:
Same as Option 1—go to Settings → Permalinks and save changes.
Critical Bonus: Redirect Old URLs to New Ones
To avoid losing SEO value from existing links, add this 301 redirect rule to send traffic from the old my-cpt-news-1 style URLs to the new ones:
function redirect_old_cpt_urls() { global $wp; $current_request = $wp->request; // Match URLs like /my-cpt-news-1/ if ( preg_match( '/^my-cpt-news-\d+$/', $current_request ) ) { // Extract the core post slug (remove the "my-cpt-" prefix) $new_slug = str_replace( 'my-cpt-', '', $current_request ); // Find the matching CPT post $post = get_page_by_path( $new_slug, OBJECT, 'my-cpt-name' ); if ( $post ) { // Redirect to the new permalink with a 301 (permanent) status wp_redirect( get_permalink( $post ), 301 ); exit; } } } add_action( 'template_redirect', 'redirect_old_cpt_urls' );
Just remember to test all your URLs after making these changes to ensure everything loads correctly—if you get 404 errors, double-check that you flushed the rewrite rules and that your CPT slug matches exactly in all code snippets.
内容的提问来源于stack exchange,提问作者Emilien Schneider

