URLs can be hard. When you have custom post types in WordPress it can be harder.
Take, for example, a custom post type for videos. Do you want your URLs to be http://example.com/videos/video-name/
or http://example.com/video/video-name/
? And do you want the archive to be http://example.com/videos/
or http://example.com/video/
? And what happens when you change your mind?
Thankfully, WordPress lets you do some weird things.
Pick Your Default
Let’s look at the video/videos idea for a moment. Individual posts should be video
but the archive should be videos
in order to grammatically make sense. When you make your custom post type there’s a parameter called has_archive
– by default it’s false. If you make it true, then it’ll have the same ‘base’ as your custom post types.
But. If you make it a string then you can make it ‘videos’ or ‘photos’ and magically your archives will have those names. That makes it pretty easy to change, just remember to re-save your permalinks after. I personally recommend doing a redirect so that video
goes to videos
(and videos/postname
go to video/postname
) so that any random bad URLs would still be caught.
Remember that you can leave it false and make a page to be a placeholder page, or you use archive-{post_type}.php
to customize it further.
When You Need Both
But… What if you need both?
This is probably a bad idea, but let’s pretend you want to have both video and videos work for all cases. That’s when you’ll need something like this:
$plural_types = array( 'videos' => 'post_type_videos', 'photos' => 'post_type_photos' ); foreach( $plural_types as $slug => $type ) { add_rewrite_rule( '^'.$slug.'/?$', 'index.php?post_type='.$type, 'top' ); add_rewrite_rule( '^'.$slug.'/page/([0-9]+)?/?$', 'index.php?post_type='.$type.'&paged=$matches[1]', 'top' ); }
In that example, I have the slug for my custom post types set to the singular, and then the $plural_types
array has the correct plural and the associated custom post type. This is tossed into a for-loop that creates a custom rewrite rule that will redirect.