4

For the purposes of my site, I have my Permalinks set to /blog/%postname%/ for all posts.

However, I need to give Posts with a specific Category (in this case, "Testimonials") its own permalink structure, where each individual post assigned the Category "Testimonials" returns as /testimonials/%postname%/ and the Category Archive page returns as /testimonials/.

Here is the code I have so far:

//Rewrite URLs for "testimonial" category
add_filter( 'post_link', 'custom_permalink', 10, 3 );
function custom_permalink( $permalink, $post, $leavename ) {
    // Get the category for the post
    $category = get_the_category($post->ID);
    if (  !empty($category) && $category[0]->cat_name == "Testimonials" ) {
        $cat_name = strtolower($category[0]->cat_name);
        $permalink = trailingslashit( home_url('/'. $cat_name . '/' . $post->post_name .'/' ) );
    }
    return $permalink;
}

add_action( 'init', 'custom_rewrite_rules' );
function custom_rewrite_rules() {
    add_rewrite_rule(
        'testimonials/([^/]+)(?:/([0-9]+))?/?$',
        'index.php?category_name=testimonials&name=$matches[1]&page=$matches[2]',
        'top' // The rule position; either 'top' or 'bottom' (default).
    );
}

This successfully returns each individual post with the category "Testimonials" as /testimonials/%postname%/. However, the Category Archive page returns as /blog/category/testimonials. I need this to just return as /testimonials/, while still returning all other Posts as /blog/%postname%/

I tried using this plugin, https://wordpress.org/plugins/custom-permalinks/, which solved the Category Archive page issue, but broke each individual testimonial post, returning them as a 404 error.

In this case, I cannot register Testimonials as a Custom Post Type as it will affect other site functionality,

2
  • Is there a reason you don't have the testimonials set as a custom post type? Commented Mar 13, 2018 at 22:12
  • The site was inherited from a previous developer. I'd like to know if I can solve this issue by rewriting the URL structure, as opposed to registering a custom post type and porting every single Post with that category over to it. Commented Mar 13, 2018 at 22:55

2 Answers 2

7

Try these steps:

Step #1: Replace this:

add_action( 'init', 'custom_rewrite_rules' );
function custom_rewrite_rules() {
    add_rewrite_rule(
        'testimonials/([^/]+)(?:/([0-9]+))?/?$',
        'index.php?category_name=testimonials&name=$matches[1]&page=$matches[2]',
        'top' // The rule position; either 'top' or 'bottom' (default).
    );
}

..with this one:

add_filter( 'category_link', 'custom_category_permalink', 10, 2 );
function custom_category_permalink( $link, $cat_id ) {
    $slug = get_term_field( 'slug', $cat_id, 'category' );
    if ( ! is_wp_error( $slug ) && 'testimonials' === $slug ) {
        $link = home_url( user_trailingslashit( '/testimonials/', 'category' ) );
    }
    return $link;
}

add_action( 'init', 'custom_rewrite_rules' );
function custom_rewrite_rules() {
    add_rewrite_rule(
        'testimonials(?:/page/?([0-9]{1,})|)/?$',
        'index.php?category_name=testimonials&paged=$matches[1]',
        'top' // The rule position; either 'top' or 'bottom' (default).
    );

    add_rewrite_rule(
        'testimonials/([^/]+)(?:/([0-9]+))?/?$',
        'index.php?category_name=testimonials&name=$matches[1]&page=$matches[2]',
        'top' // The rule position; either 'top' or 'bottom' (default).
    );
}

Step #2: Go to the Permalink Settings page, and click on the Save Changes button without actually making any changes.

2
  • 1
    This worked, thank you very much. Encouraging to know that thinking to add another "add_rewrite_rule" function was on the right track, but I had not known about the "category_link" filter. Thanks again! Commented Mar 14, 2018 at 15:32
  • You're very welcome. =)
    – Sally CJ
    Commented Mar 15, 2018 at 0:16
0

Why not just add the post id then? If that's all you need? You could just do this with query_vars

add_filter('query_vars', 'my_query_vars' );

You only need to check if you are in the 'special' category and if yes, add the var. Then utilizing the pre_get_posts hook, check if your post contains an ID and if yes change your query to get desired post.

1
  • without adding actual rewrite rules wordpress will not know how to parse the url. There is no way to go around it Commented Mar 14, 2018 at 7:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.