How to get permalinks with category base working with sub-categories

I ran into an issue with a site that needs the category base also included in the custom permalink structure. I know this is an issue and I have read many posts like this that gave me some insight…

I need to get the permalinks to work like this:

Read More
http://www.new1450.dev/industries/ {Main blog post only showing category selection}
http://www.new1450.dev/industries/development/ {a parent category}
http://www.new1450.dev/industries/development/parent-category-i/ {child of parent}
http://www.new1450.dev/industries/development/parent-category-i/child-category-i/ {child of child}
http://www.new1450.dev/industries/development/parent-category-i/child-category-i/some-cool-post/ {actual post}

My permalink settings are:
Custom Structure:

/industries/%category%/%postname%/

Category Base:

industries/.

This gets me working with:

http://www.new1450.dev/industries/ {Main blog post only showing category selection}
http://www.new1450.dev/industries/development/ {a parent category}
http://www.new1450.dev/industries/development/parent-category-i/child-category-i/some-cool-post/ {actual post}

So it appears it’s just the child categories that pose a problem..

http://www.new1450.dev/industries/development/parent-category-i/ {child of parent}
http://www.new1450.dev/industries/development/parent-category-i/child-category-i/ {child of child}

I am able to get the category ID by intercepting the 404 but I cannot see how to load the categories page with the proper category ID.

So my question is: Is there a way to load the categories page by calling some internal command or will I have to write my own way of loading the categories page? I was hoping that I could use a WP function as this would be ideal. if this is the latter, is there anything special I need to be aware of? I do know I have to set: status_header(200); but wanted to know if there are any other headers or important steps that need to be taken.

Also, a redirect will not work for my purpose. I need to load the categories page with the new ID. If it helps, the hook I am using in WP to catch the 404 is: template_redirect

Thanks for any information you can provide on this subject.

Related posts

1 comment

  1. I was able to get this to work pretty easily actually. I am now able to have my category base in my permalinks. This allows me to now have URLs like:

    http://www.new1450.dev/industries/ {Main blog post only showing category selection}
    http://www.new1450.dev/industries/development/ {a parent category}
    http://www.new1450.dev/industries/development/parent-category-i/ {child of parent}
    http://www.new1450.dev/industries/development/parent-category-i/child-category-i/ {child of child}
    http://www.new1450.dev/industries/development/parent-category-i/child-category-i/some-cool-post/ {actual post}
    

    This should work for any level of category nesting.

    My Permalink settings:

    Custom Structure: /industries/%category%/%postname%/

    Category base: industries/. (/. is required as it prevents 404s for post)

    Code:

    /**
     * Fix 404 for permalinks using category_base
     */
    function permalinkWithCategoryBaseFix() {
        global $wp_query;
        // Only check on 404's
        if ( true === $wp_query->is_404) {
            $currentURI = !empty($_SERVER['REQUEST_URI']) ? trim($_SERVER['REQUEST_URI'], '/') : '';
            if ($currentURI) {
                $categoryBaseName = trim(get_option('category_base'), '/.'); // Remove / and . from base
                if ($categoryBaseName) {
                    // Perform fixes for category_base matching start of permalink custom structure
                    if ( substr($currentURI, 0, strlen($categoryBaseName)) == $categoryBaseName ) {
                        // Find the proper category
                        $childCategoryObject = get_category_by_slug($wp_query->query_vars['name']);
                        // Make sure we have a category
                        if (is_object($childCategoryObject)) {
                            $paged = ($wp_query->query_vars['paged']) ? $wp_query->query_vars['paged']: 1;
                            $wp_query->query(array(
                                                  'cat' => $childCategoryObject->term_id,
                                                  'paged'=> $paged
                                             )
                            );
                            // Set our accepted header
                            status_header( 200 ); // Prevents 404 status
                        }
                        unset($childCategoryObject);
                    }
                }
                unset($categoryBaseName);
            }
            unset($currentURI);
        }
    }
    
    add_action('template_redirect', 'permalinkWithCategoryBaseFix');
    

    I originally had:

    $childCategoryObject = get_category_by_slug( ((!empty($wp_query->query_vars['page']) && $wp_query->query_vars['page'] > 1) ? $wp_query->query_vars['category_name'] : $wp_query->query_vars['name']) );
    

    in place of:

    $childCategoryObject = get_category_by_slug($wp_query->query_vars['name']);
    

    but it seems that check wasn’t necessary. I left this comment in case I had it for a reason I couldn’t remember…

    Also, I had issues with my default category pagination… A quick search returns many people with the same issue (won’t go past page 2) so I added this fix too. I found this fix in a WordPress plugin: Category pagination fix. I updated the code and the fix is below:

    /**
     * Fix the problem where next/previous of page number buttons are broken of posts in a category when the custom permalink
     * The problem is that with a url like this:
     * /categoryname/page/2
     * the 'page' looks like a post name, not the keyword "page"
     */
    function fixCategoryPagination($queryString) {
        if (isset($queryString['name']) && $queryString['name'] == 'page' && isset($queryString['page'])) {
            unset($queryString['name']);
            // 'page' in the query_string looks like '/2', so i'm exploding it
            list($delim, $page_index) = explode('/', $queryString['page']);
            $queryString['paged'] = $page_index;
        }
        return $queryString;
    }
    
    add_filter('request', 'fixCategoryPagination');
    

    Note: It should be noted, the pagination fix was only necessary on the parent categories. The child categories had no issue with pagination.

Comments are closed.