0

i am trying to give a specific category posts it's own permalink. Followed the steps from this topic (Give specific category its own permalink structure) but the posts are giving a 404 error.

Cleared cache, saved permalinks under settings but to no avail.

Would appreciate help in fixing this.

Thanks

here is my code:

//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 == "Foodguide" ) {
        $cat_name = strtolower($category[0]->cat_name);
        $permalink = trailingslashit( home_url('/'. $cat_name . '/' . $post->ID . '/' . $post->post_name .'/' ) );
    }
    return $permalink;
}

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 ) && 'foodguide' === $slug ) {
        $link = home_url( user_trailingslashit( '/foodguide/', 'category' ) );
    }
    return $link;
}

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

    add_rewrite_rule(
        'foodguide/([^/]+)(?:/([0-9]+))?/?$',
        'index.php?category_name=foodguide&name=$matches[1]&page=$matches[2]',
        'top' // The rule position; either 'top' or 'bottom' (default).
    );
}
  • Post your code. – Sally CJ Sep 26 at 4:41
  • Updated the post with the code. – Praveen Kumar Sep 26 at 5:21
  • The post permalink includes the post ID (e.g. example.com/foodguide/1/hello-world), but your rewrite rules doesn't include the pattern for that post ID. So remove the '/' . $post->ID . (in your custom_permalink function). Otherwise, you need to change the rewrite rules/regex. – Sally CJ Sep 26 at 6:59
  • Can you help me out with the correct regex pls? – Praveen Kumar Sep 26 at 12:53
  • Yes, but I'm sorry for the delay.. quite busy lately. – Sally CJ Oct 1 at 15:42
0

First off, the add_rewrite_rule() syntax is add_rewrite_rule( 'RegEx pattern', 'WordPress query string/vars', 'position/priority - top or bottom' ).

Now I could see you're trying to have the following permalink structure:

Structure: example.com/foodguide/<post ID>/<post slug>
Example:   example.com/foodguide/1/sample-food-guide

But your rewrite rule (the second one in your code) does not have the proper RegEx subpattern for the post ID part in the permalink; hence, the permalink leads to a 404 error page.

And to fix the issue, you can add \d+/ to the rewrite rule:

add_rewrite_rule(
    'foodguide/\d+/([^/]+)(?:/([0-9]+))?/?$', // <- here, add the \d+/
    'index.php?category_name=foodguide&name=$matches[1]&page=$matches[2]',
    'top'
);

Alternatively, in the RegEx pattern, you can "capture" the post ID (i.e. use (\d+)) and not the post slug, and then in the WordPress query, use the p (i.e. ID) parameter instead of name (i.e. slug):

add_rewrite_rule(
    'foodguide/(\d+)/[^/]+(?:/([0-9]+))?/?$', // capture the \d+
    // $matches[1] is now the post ID, so use &p= instead of &name=
    'index.php?category_name=foodguide&p=$matches[1]&page=$matches[2]',
    'top'
);

PS: Don't forget to flush the rewrite rules — just visit the permalink settings page.

UPDATE

If you want the post permalink to end with a .html, then:

  1. In custom_permalink(), make the following change:

    // Change this:
    $permalink = trailingslashit( home_url('/'. $cat_name . '/' . $post->ID . '/' . $post->post_name .'/' ) );
    
    // To this:
    $permalink = untrailingslashit( home_url( '/'. $cat_name . '/' . $post->ID . '/' . $post->post_name . '.html' ) );
    
  2. In custom_rewrite_rules(), change the second add_rewrite_rule() to this:

    add_rewrite_rule(
        '^foodguide/(\d+)/[^/]+\.html$',
        'index.php?category_name=foodguide&p=$matches[1]',
        'top'
    );
    
  3. After the function custom_rewrite_rules() { ... }, add this:

    function cancel_canonical_redirect( $wp ) {
        if ( '^foodguide/(\d+)/[^/]+\.html$' === $wp->matched_rule ) {
            remove_action( 'template_redirect', 'redirect_canonical' );
        }
    }
    add_action( 'parse_request', 'cancel_canonical_redirect' );
    

    That would prevent "adding" the ending slash (/) to the permalink URL.

And once again, don't forget to flush the permalinks.

Also, I've not added support for paginated requests (i.e. posts having the <!--nextpage--> tag or the Page Break block in Gutenberg); and if you need that, let me know.

UPDATE 2

For paginated requests with this permalink/URL structure:

example.com/foodguide/<post ID>/<post slug>/page-<page number>.html
  1. In custom_rewrite_rules(), change the second add_rewrite_rule() to this:

    add_rewrite_rule(
        '^foodguide/(\d+)/[^/]+(?:/page-(\d+)|)\.html$',
        'index.php?category_name=foodguide&p=$matches[1]&page=$matches[2]',
        'top'
    );
    
  2. Change the cancel_canonical_redirect to (* the RegEx pattern needs to match the one used in the above add_rewrite_rule()):

    function cancel_canonical_redirect( $wp ) {
        if ( '^foodguide/(\d+)/[^/]+(?:/page-(\d+)|)\.html$' === $wp->matched_rule ) {
            remove_action( 'template_redirect', 'redirect_canonical' );
        }
    }
    add_action( 'parse_request', 'cancel_canonical_redirect' );
    
  3. After the above code, add this:

    function custom_wp_link_pages_link( $link, $i ) {
        if ( in_category( 'foodguide' ) ) {
            $name = get_post_field( 'post_name' );
            $link = str_replace(
                "{$name}.html/$i/",     // replace example.com/foodguide/<post ID>/<post slug>.html/<page number>/
                "$name/page-{$i}.html", // with example.com/foodguide/<post ID>/<post slug>/page-<page number>.html
                $link
            );
        }
        return $link;
    }
    add_filter( 'wp_link_pages_link', 'custom_wp_link_pages_link', 10, 2 );
    

And as always, be sure to flush the permalinks.

  • Thank you so much. This works great. If i want to keep this structure, what change should i be making? Structure: example.com/foodguide/<post ID>/<post slug>.html Example: example.com/foodguide/1/sample-food-guide.html – Praveen Kumar Oct 4 at 5:09
  • I already answered the original question, so could you please accept the answer? But don't worry, I'll update the answer with the new structure you need (when I get back to my computer). – Sally CJ Oct 4 at 6:29
  • Hi. yes, i have accepted the answer already :) – Praveen Kumar Oct 4 at 10:01
  • Thanks. :) Check the "UPDATE" part and let me know. – Sally CJ Oct 4 at 17:27
  • Thank you so much. As of now, none of the posts are paginated and i don't use Gutenberg. But just in case if it becomes an issue later, can you please share the support code also? – Praveen Kumar Oct 6 at 4:29
0

Please remove the code from functions.php. Instead of that do the following,

Step 1:Go to the settings -> permalink in the WordPress dashboard(Refer to this link). enter image description here

Step 2:Select the Custom Structure in the permalink settings page(Refer to this link). enter image description here

Step 3:Change the Permalink to our requirement and click the save changes button(Refer this link). enter image description here

Step 4:Then the permalink of the post is changed as we given in the settings page(Refer this link). enter image description here

  • Hi This is not the answer i was after. What i am looking for is to rewrite the url structure for one particular category posts alone and not for the entire site. – Praveen Kumar Sep 30 at 16:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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