Ask your WordPress questions! Pay money and get answers fast! Comodo Trusted Site Seal
Official PayPal Seal

Custom Post Type & Custom Taxonomy Rewrite Maintaining Defaults WordPress

I have a registered taxonomy (wps_type) and 2 custom post types (wps_business, wps_location) in that order.

The registered taxonomy has rewrite arg set to slug => type and the post types have slug => business & slug => location already set. I need a custom smart permalink rewrite rule where all of the following are available.

Defaults Work (and still need to work):

<blockquote>http://domain.com/post-type/post-name => http://domain.com/business/post-name
http://domain.com/post-type/post-name => http://domain.com/location/post-name
http://domain.com/taxonomy/term-name => http://domain.com/type/term-name</blockquote>

But what I need is:

<blockquote>http://domain.com/post-type/taxonomy => http://domain.com/location-post-name/type-term-name</blockquote>

So I believe using post_type_link filter may not work, but I could be wrong.

In case you need them, here are their registrations from get_post_type_object and get_taxonomy:
//Location
stdClass Object
(
[labels] => stdClass Object
( ... )

[description] =>
[publicly_queryable] => 1
[exclude_from_search] =>
[capability_type] => post
[map_meta_cap] => 1
[_builtin] =>
[_edit_link] => post.php?post=%d
[hierarchical] =>
[public] => 1
[rewrite] => Array
(
[slug] => location
[with_front] => 1
[pages] => 1
[feeds] => 1
)

[has_archive] => 1
[query_var] => wps_location
[register_meta_box_cb] =>
[taxonomies] => Array
(
)

[show_ui] => 1
[menu_position] => 6
[menu_icon] =>
[permalink_epmask] => 1
[can_export] => 1
[show_in_nav_menus] => 1
[show_in_menu] => edit.php?post_type=wps_business
[show_in_admin_bar] =>
[post_type] => wps_location
[name] => wps_location
[cap] => stdClass Object
( ... )

[label] => Locations
)

//Business
stdClass Object
(
[labels] => stdClass Object
( ... )

[description] =>
[publicly_queryable] => 1
[exclude_from_search] =>
[capability_type] => post
[map_meta_cap] => 1
[_builtin] =>
[_edit_link] => post.php?post=%d
[hierarchical] =>
[public] => 1
[rewrite] => Array
(
[slug] => business
[with_front] => 1
[pages] => 1
[feeds] => 1
)

[has_archive] => 1
[query_var] => wps_business
[register_meta_box_cb] =>
[taxonomies] => Array
(
[0] => wps_business_type
)

[show_ui] => 1
[menu_position] => 6
[menu_icon] =>
[permalink_epmask] => 1
[can_export] => 1
[show_in_nav_menus] => 1
[show_in_menu] => 1
[show_in_admin_bar] => 1
[post_type] => wps_business
[name] => wps_business
[cap] => stdClass Object
( ... )

[label] => Businesses
)

//Business Types
stdClass Object
(
[hierarchical] => 1
[update_count_callback] =>
[rewrite] => Array
(
[slug] => business-type
[with_front] => 1
[hierarchical] =>
)

[query_var] => wps_business_types
[public] => 1
[show_ui] => 1
[show_tagcloud] => 1
[_builtin] =>
[labels] => stdClass Object
( ... )

[show_in_nav_menus] => 1
[post_types] => Array
(
[0] => wps_business
)

[taxonomy] => wps_business_types
[cap] => stdClass Object
(
[manage_terms] => manage_categories
[edit_terms] => manage_categories
[delete_terms] => manage_categories
[assign_terms] => edit_posts
)

[name] => wps_business_types
[object_type] => Array
(
[0] => wps_business
)

[label] => Business Types
)

Answers (2)

2012-06-07

John Cotton answers:

HI Travis

I'm not clear what you need...

http://domain.com/post-type/taxonomy => http://domain.com/location-post-name/type-term-name

Are you saying that a location post named London and with a type of name Books should have the link:

http://domain.com/location-london/type-books

?

And if it did, what should actually be displayed? The post named London?


Travis Smith comments:

John,

For example, I have a location named London. Then I have a business type (hierarchical taxonomy) of Restaurants.
The URL should be: http://domain.com/london/restaurants/

Likewise, if I have a business sub-type of Mexican (under Restaurants), the URL should be: http://domain.com/london/restaurants/mexican/

And so on...


John Cotton comments:

Can I ask why you've made the location a custom post type rather than a taxonomy?

Also, in your example, what should http://domain.com/london/restaurants/ show? All posts tagged restaurants or just the London post?


Travis Smith comments:

Hello John,

Basically, I need post meta and WordPress doesn't handle term meta except via options which is slower than using a Custom Post Type. So, I have some code on the backed forcing the CPT to serve double duty. Until WordPress solves ticket [[LINK href="http://core.trac.wordpress.org/ticket/10142"]]#10142[[/LINK]], it's the best solution as far as optimization. Anyways.

The ugly link is this: http://domain.com/?wps_location={#post->post_name}&wps_business={$term->slug} created via home_url.
home_url( '/?' . $post->post_type . '=' . $post->post_name . '&' . $term->taxonomy . '=' . $term->slug )


Travis Smith comments:

To answer your question, I handle the display of the page via template_include pushing to one of two templates based on get_post_type(), get_query_var() and the basic conditionals.


Travis Smith comments:

If you'd like to chat, I am on IRC in #wordpress username wpsmith. Feel free to hit me up!


John Cotton comments:

Try this in your functions.php:


function my_insert_rewrite_rules( $rules ) {
$newrules = array();

$newrules['^location-(.*)/type-(.*)$'] = 'index.php?wps_location=$matches[1]&wps_business=$matches[2]';

return $newrules + $rules;
}
add_filter('rewrite_rules_array','my_insert_rewrite_rules');


Save Permalinks to active.

But I think the above might confuse WordPress as it wouldn't know whether it was showing a single post page or a term archive page.

Perhaps your template redirect will handle that.


John Cotton comments:

<blockquote>Basically, I need post meta and WordPress doesn't handle term meta</blockquote>

...WordPress doesn't, but you can!

[[LINK href="http://codex.wordpress.org/Function_Reference/get_metadata"]]get_metadata[[/LINK]] is designed to take a type (any string). So, providing you create a meta structured table in the database, you can use that function (and its associates) to have term meta. There are even hooks for you to add your own UI to the taxonomy editing pages.


Travis Smith comments:

John,

Code didn't work and I don't care for the 'location-' or 'type-' portions.

I'll definitely look into get_metadata. If you know of any useful links please share.

Thanks,

Travis


John Cotton comments:

<blockquote>Code didn't work</blockquote>
You definitely saved your permalinks?

You don't say what the outcome was but either WordPress is confused (as I predicted) or your template redirection code is at fault (perhaps you could post that?).


and I don't care for the 'location-' or 'type-' portions.

I took those from your example at the top...

But without them, it's never going to work as the effective regex would match all pages and posts!!

If you want to have terms as part of the url, you need to have something to lock onto in the regex. That means either some extra fixed portion (like location-) or creating an entry for every term.

So, for your code, something like this would allow you to grab the custom query var location-name in template_redirect


function theme_insert_rewrite_rules( $rules ) {
$newrules = array();

$terms = get_terms('wps_type', array( 'hide_empty' => false ) );

foreach( $terms as $term ) {
$newrules['^(.*)/'.$term->slug.'$'] = 'index.php?location-name=$matches[1]&wps_type='.$term->slug;
}

return $newrules + $rules;
}
add_filter('rewrite_rules_array','theme_insert_rewrite_rules');

function theme_insert_query_vars($vars) {
array_push( $vars, 'location-name' );
return $vars;
}
add_filter('query_vars','theme_insert_query_vars');


You'd have to save your permalinks every time you added a new term, or you could and a permalink refresh in a hook for the term create/update.


Travis Smith comments:

<blockquote><em>You'd have to save your permalinks every time you added a new term, or you could and a permalink refresh in a hook for the term create/update.</em></blockquote>

Yes I definitely do not want to do that.


Yet,
http://domain.com/?wps_location=london => http://domain.com/location/london/
and
http://domain.com/?wps_type=consulting => http://domain.com/type/consulting/

So I am just looking to have:
http://domain.com/?wps_location=london&wps_type=consulting => http://domain.com/london/consulting

So seeing your point, is it possible for:
http://domain.com/?wps_location=london&wps_type=consulting => http://domain.com/directory/london/consulting


Travis Smith comments:

If it will help, I don't mind adding a query var of directory or something to help with the identification of the URL. So if I need I can make the link: http://domain.com/?wps_directory=true&wps_location=london&wps_type=consulting but prefer not to (just a preference).


Travis Smith comments:

By the way I am using Rewrite Rules Inspector to flush rules and test.


John Cotton comments:

<blockquote>So seeing your point, is it possible for:
http://domain.com/?wps_location=london&wps_type=consulting => http://domain.com/directory/london/consulting</blockquote>

Absolutely. The /directory/ gives you the recognisable lock.

Adjust the earlier code as follows:

$newrules['^directory/(.*)/(.*)$'] = 'index.php?wps_location=$matches[1]&wps_business=$matches[2]';

<blockquote>By the way I am using Rewrite Rules Inspector to flush rules and test.</blockquote>

I don't know this - is it a plugin? I tend to avoid plugins as they rarely do exactly what I want.

But the above code works simply by saving permalinks from your Settings > Permalinks menu item.


Travis Smith comments:

<blockquote><em>I don't know this - is it a plugin? I tend to avoid plugins as they rarely do exactly what I want.</em></blockquote>

It is an Automattic plugin released last month to just inspect rewrite rules. Check it out. I've found it extremely useful during this exercise.

However, the above code does not work here, regrettably. I definitely appreciate your attention to this. Shot you a message.


John Cotton comments:

<blockquote>However, the above code does not work here, regrettably.</blockquote>
What do you get?

If everything you told me is true, then that will work.

If it doesn't, something else is amiss...

Any guy who can use germane in a sentence gets my respect :) = so just tell me how it is....

2012-06-07

Milan Petrovic answers:

My plugin has this feature:
http://www.gdcpttools.com/features/custom-permalinks/

You can set permalinks for posts and you can create archives links that filter posts by post type and taxonomy.

Milan


Travis Smith comments:

I don't want a plugin for this. I need the code, which should be a simple function or two.


Travis Smith comments:

Don't get me wrong Milan, I've reviewed your plugin and it's great. I just need this bit for a custom client plugin. I hate regex and steer away from rewrites, but it's in the SOW this time.


Travis Smith comments:

If you'd like to chat, I am on IRC in #wordpress username wpsmith. Feel free to hit me up!