Removing Base From Custom Post Type URL in WordPress: Method 2 [Method Breaks Pages]

A second method for removing the base from your custom post type URLs in WordPress that won't (completely) break RSS.

WP Rewrite

Update: So, once again I found a major flaw with this method. Regular pages will not work using this method. I have reverted back to using the slug for series for now. When I have time I’ll be looking further into this. If you don’t use the default pages feature, this feature will work and allow you to keep custom RSS feeds.

So yesterday I made a post that showed how to remove the base or slug from custom post type URLs. Well, the thing that I really didn’t foresee was that it would completely break RSS or the built-in WordPress feed system. Whoops. I don’t expect readership to pick up here much so losing RSS is not a problem for me, but what is a problem is the way I generate my sitemaps.

While developing VGXCheck I wrote a library that dynamically creates sitemaps so I can keep Google, MSN, and whatever search engine up to date with our posts. Instead of creating individual files or creating individual pages in WordPress where I would need to create individual templates, I use the add_feed() function built into WordPress to setup feeds that I can use as XML sitemaps. Using the method mentioned above completely broke any custom feeds I had setup. I did some digging and came up with an alternative method that works for my purposes.

Before I start I should note that this method isn’t the perfect fit for what I wanted, but it works for what I need. Ideally I would like to come up with a method that preserves full Feed functionality, but unfortunately I was unable to do this at this time. With this method (from here on out referred to as “Method 2“) you will keep functionality with all custom feeds, but will lose access to the default feeds (http://siteurl.com/feed). Comment feeds on your posts will also work. Lets start by taking a look at our function that creates the custom post type again.

register_post_type('series', array(
     'label' => __('Series'),
     'singular_label' => __('Series'),
     'public' => true,
     'publicly_queryable' => true,
     'show_ui' => true,
     'show_in_menu' => true,
     'menu_position' => 5,
     'capability_type' => 'page',
     'supports' => array('title','editor','thumbnail','excerpt','comments','revisions'),
     'query_var' => 'series',
     'taxonomies' => array('post_tag','category'),
     'rewrite' => false
));

Once again we want to focus on the rewrite property. This time we set it to false because we are going to use a different method to configure the URL rewriting.


add_rewrite_tag("%series%", '([^/]+)', "series=");
add_permastruct('series', '/%series%/', false);

These functions weren’t included in the previous method. add_rewrite_tag() allows you to create a variable or placeholder that will be interchanged with the slug of your custom post when WordPress is rewriting your URL. The function takes three arguments you’re going to need to input.

Argument 1: The tag name. This can be whatever you want, but must start and end with a “%”.

Argument 2: The regular expression to help identify the slug you want from the query string. If you’re not familiar with regular expressions you may want to do some Google searching on it or you can try to use the one I put together in the code above.  I hate Regex, but it’s a necessary evil in many cases.

Argument 3: Tells WordPress how to interpret the tag. Basically adds what’s in the third argument in front of whatever regex finds so that WordPress can find your post.

add_permastruct() is what your end result will be in your URL and also takes three arguments.

Argument 1: The name of the permalink structure. Your choice.

Argument 2: The permalink structure itself. You can see that I used the tag established in add_rewrite_tag() to identify where I want the slug from the post. The permalink structure works from the base url (e.g. http://bigblackguy.com), so basically what I did in the code above was tell WordPress that I want the slug of the post to be between two forward slashes (/) at the end of my base url (all together now: http://bigblackguy.com/this-is-my-post/).

Argument 3: There are additional arguments you can put into an array for the permalink structure. If you need to go a bit beyond what I’m covering here I suggest you check out the arguments in the codex.

The functions use above should take care of removing the base from our custom post type urls, but we aren’t done yet. All of the functions used above need to be done during ‘init’ so we need to put them in another function that we can call using add_action(). My end result looks like this:


add_action('init','theFunction);
function theFunction(){
register_post_type('series', array(
     'label' => __('Series'),
     'singular_label' => __('Series'),
     'public' => true,
     'publicly_queryable' => true,
     'show_ui' => true,
     'show_in_menu' => true,
     'menu_position' => 5,
     'capability_type' => 'page',
     'supports' => array('title','editor','thumbnail','excerpt','comments','revisions'),
     'query_var' => 'series',
     'taxonomies' => array('post_tag','category'),
     'rewrite' => false
));

add_rewrite_tag("%series%", '([^/]+)', "series=");
add_permastruct('series', '/%series%/', false);

After this you need to flush the rewrite rules by going to your permalink settings and saving. Don’t need to change anything in that menu, just hit save. Like I said, your default feeds will no longer work, but any custom ones you setup will still work. My sitemap index was setup with the name “sitemap-index”, so the URL to reach that now is http://bigblackguy.com/feed/sitemap-index. If you go to /feed it will just give you a 404. If you want to use this method and still have RSS work you will need to have create custom RSS feeds. That was something I was planning on doing at some point for this site so it’s not big deal for me, but I know it’s a bigger deal for others. So, to recap:

  1. Set the ‘rewrite’ attribute to false when your custom post type is registers.
  2. Use add_rewrite_tag() to create a rewrite variable.
  3. Use add_permastruct() to inject the rewrite rules structure into WordPress.
  4. Flush rewrite rules by going to your permalink settings and saving (WordPress Admin > Settings > Permalink). No need to change anything.

I’ll be looking for ways to complete my objective without disrupting normal use of WordPress feeds, but until then this is the best I have.