In the pl_custom_rewrite_rules()
function, change the REGEX pattern to ^new_slug/(.*)$
as in:
add_rewrite_rule( '^new_slug/(.*)$', 'index.php?name=$matches[1]', 'top' );
because WordPress strips the preceeding /
from the request path (WP::$request
), so using the ^/new_slug
never evaluates to true
.
Additionally, in the pl_custom_permalink()
function, remove the global $post;
line because the function already receiving the proper post data (i.e. $post
) as in function pl_custom_permalink( $permalink, $post, $leavename )
.
The full code I used, without any re-indentation: (tried & tested working on WordPress 4.9.8)
add_filter( 'post_link', 'pl_custom_permalink', 10, 3 );
function pl_custom_permalink( $permalink, $post, $leavename ) {
if ( has_category( 'My Category', $post->ID) ) {
$permalink = trailingslashit( home_url('/new_slug/'. $post->post_name . "https://wordpress.stackexchange.com/" ) );
}
return $permalink;
}
add_action('init', 'pl_custom_rewrite_rules');
function pl_custom_rewrite_rules( $wp_rewrite ) {
add_rewrite_rule( '^new_slug/(.*)$', 'index.php?name=$matches[1]', 'top' );
}
Here’s the code for the canonical redirect, which redirects example.com/name-of-my-post
to example.com/new_slug/name-of-my-post
:
add_action( 'wp', function( $wp ){
// If it's a single Post and it's in the 'My Category' category, redirect to
// the canonical version. Also check if the request path doesn't start with
// new_slug/ as in http://example.com/new_slug/hello-world/
if ( ! preg_match( '#^new_slug/#', $wp->request ) &&
is_singular() && in_category( 'My Category' ) ) {
wp_redirect( get_permalink() );
exit;
}
} );