Warning: Please do not give out any FTP or ssh credentials to anyone, unless you trust them completely. Giving out login details is dangerous.
If the asker does not get an answer then they have 10 days to request a refund.
$50
(Hierarchical) Custom Post Type & Taxonomy Permalinks
I've a custom post type 'books', a registered taxonomy 'book_taxonomy' and some trouble with my permalinks:
I'd like my permalinks for the cpt 'books' look like this:
domain.com/baseurl/--> static page with custom template
domain.com/baseurl/[book genre]/[book name]/ --> book-article
domain.com/baseurl/[book genre]/ --> archive of all book-articles matching 'book genre'
The Cherry on the cake would be a support of hierarchical taxonomies. E.g.:
domain.com/baseurl/[book genre]/[book sub genre]/[book name]/ --> book-article
domain.com/baseurl/[book genre]/[book sub genre]/[...]/[book name]/ --> book-article
After 'some' unsuccessful trial and error attempts based on snippets and tutorials I found on the web, I would be very thankfull for your help:-)
I think the only PHP you can use from my attempts, is this:
add_action('init', 'post_type_books');
function post_type_books() {
register_post_type('books',
array(
'labels' => array('name' => __('Books')),
'public' => true,
'capability_type' => 'post',
'has_archive' => true,
'hierarchical' => false,
'query_var' => true,
'rewrite' => array('with_front'=>false)
)
);
}
add_action( 'init', 'taxonomy_books', 0 );
function taxonomy_books() {
register_taxonomy ('book_taxonomy',array('books'),
array(
'labels' => array('name' => __('Genre')),
'show_ui' => true,
'hierarchical' => true,
'query_var' => true,
'rewrite' => false
)
);
} Supplement: Well, I've forgot to say that I'm not looking for a plugin-based solution... I'd like to "hardcode" it to my functions.php :-)
This question has been answered.
mark | 06/16/12 at 2:45pm
Edit
Previous versions of this question:
06/16/12 at 2:50pm
| 06/16/12 at 9:50pm
The experts have suggested, on average, a prize of $87 for this question.
(2) Possible Answers Submitted...
See a chronological view of answers?
Warning: Please do not give out any FTP or ssh credentials to anyone, unless you trust them completely. Giving out login details is dangerous.
-

Last edited:
06/16/12
2:55pmArnav Joy says:try this
add_action('init', 'post_type_books');
function post_type_books() {
register_post_type('books',
array(
'labels' => array('name' => __('Books')),
'public' => true,
'capability_type' => 'post',
'has_archive' => true,
'hierarchical' => false,
'query_var' => true,
'rewrite' => array('with_front'=>false)
)
);
}
add_action( 'init', 'taxonomy_books', 0 );
function taxonomy_books() {
register_taxonomy ('book_taxonomy',array('books'),
array(
'labels' => array('name' => __('Genre')),
'show_ui' => true,
'hierarchical' => true,
'query_var' => true,
'rewrite' => true
)
);
}- 06/16/12 3:06pm
mark says:Well, no: that doesn't have any effect... I think it's not that simple:-(
I'm sure we'll have to add a filter with some new rewrite rules for the cpt. But I don't know how this filter should look like... - 06/16/12 3:09pm
Arnav Joy says:write this after the above code in functions.php
flush_rewrite_rules(); - 06/16/12 3:15pm
Arnav Joy says:or try this
function my_em_rewrite_flush(){
global $wp_rewrite;
$wp_rewrite->flush_rules();
}
add_action('init','my_em_rewrite_flush'); - 06/16/12 3:22pm
Arnav Joy says:try this
add_action( 'init', 'taxonomy_books', 0 );
function taxonomy_books() {
register_taxonomy ('book_taxonomy',array('books'),
array(
'labels' => array('name' => __('Genre')),
'show_ui' => true,
'hierarchical' => true,
'query_var' => true,
'rewrite' => array( 'slug' => 'books/type' ),
)
);
} - 06/16/12 3:28pm
Arnav Joy says:you can check this plugin
http://wordpress.org/extend/plugins/permalinks-for-hierarchical-custom-post-types/ - 06/16/12 4:25pm
mark says:Hey Arnav,
thanks for your help, but I think this isn't the way we'll get it to work :-) I'm quite sure we'll HAVE to set up and add some specific rewrite rules.
Somthink like this or maybe not:
global $wp_rewrite;
$book_structure = '/mybooks/%book_taxonomy%/%books%';
$wp_rewrite->add_rewrite_tag("%books%", '([^/]+)', "books=");
$wp_rewrite->add_permastruct('books', $book_structure, false);
And we'll have to add a filter to translate the permalink tags. Somthink like that could be found here:
http://shibashake.com/wordpress-theme/custom-post-type-permalinks-part-2
But as I said: I already worked on an trial and error 'method' on this for 'some' hours and couldn't get it working.
Flushing the rules without defining new ones can not have any effect - am I wrong?
BTW, another question: Is there any difference between
andflush_rewrite_rules();
? In the past I've only used the first one...
function my_em_rewrite_flush(){
global $wp_rewrite;
$wp_rewrite->flush_rules();
}
add_action('init','my_em_rewrite_flush');
Plugin: As I wrote, I'm not looking for a plugin-based solution... I realy NEED to hardcode the rules into my functions.php :-/
- 06/16/12 3:06pm
-

Last edited:
06/16/12
3:43pmDaniel Yoen says:try this plugin :
http://wordpress.org/extend/plugins/custom-post-type-ui/
hope this help :)- 06/16/12 8:19pm
Daniel Yoen says:try this :
<?php
function swi_post_type_books()
{
register_post_type('books', array(
'labels' => array(
'name' => __('Books')
),
'public' => true,
'capability_type' => 'post',
'has_archive' => true,
'hierarchical' => false,
'query_var' => true,
'publicly_queryable' => true,
'query_var' => true,
'rewrite' => false
));
register_taxonomy('books_taxonomy', array(
'books'
), array(
'labels' => array(
'name' => __('Genre')
),
'show_ui' => true,
'hierarchical' => true,
'query_var' => true,
'rewrite' => false
));
}
function swi_custom_rewrite_post_type()
{
global $wp_rewrite;
add_rewrite_tag('%books_cat%', '([^/]+)');
add_rewrite_tag('%books_subcat%', '([^/]+)');
$books_structure = '/mybooks/%books_cat%/%books_subcat%/%books%';
$wp_rewrite->add_rewrite_tag("%books%", '([^/]+)', "books=");
$wp_rewrite->add_permastruct('books', $books_structure, false);
}
function swi_books_permalink($permalink, $post_id, $leavename)
{
$post = get_post($post_id);
$rewritecode = array(
'%year%',
'%monthnum%',
'%day%',
'%hour%',
'%minute%',
'%second%',
$leavename ? '' : '%postname%',
'%post_id%',
'%category%',
'%author%',
$leavename ? '' : '%pagename%',
'%books_cat%',
'%books_subcat%'
);
if ('' != $permalink && !in_array($post->post_status, array(
'draft',
'pending',
'auto-draft'
)))
{
$unixtime = strtotime($post->post_date);
$category = '';
if (strpos($permalink, '%category%') !== false)
{
$cats = get_the_category($post->ID);
if ($cats)
{
usort($cats, '_usort_terms_by_ID');
$category = $cats[0]->slug;
if ($parent = $cats[0]->parent)
$category = get_category_parents($parent, false, '/', true) . $category;
}
if (empty($category))
{
$default_category = get_category(get_option('default_category'));
$category = is_wp_error($default_category) ? '' : $default_category->slug;
}
}
$post_type = $post->post_type;
$books_cat = '';
$cat_parent = '';
if (strpos($permalink, '%books_cat') !== false)
{
$terms = wp_get_object_terms($post->ID, 'books_taxonomy');
if (!is_wp_error($terms) && !empty($terms))
{
foreach ($terms as $term)
{
if ($term->parent == 0)
{
$books_cat = $term->slug;
$cat_parent = $term->term_id;
break;
}
}
}
}
$books_subcat = '';
if (strpos($permalink, '%books_subcat%') !== false && !empty($cat_parent))
{
foreach ($terms as $term)
{
if ($term->parent == $cat_parent)
{
$books_subcat = $term->slug;
break;
}
}
}
$author = '';
if (strpos($permalink, '%author%') !== false)
{
$authordata = get_userdata($post->post_author);
$author = $authordata->user_nicename;
}
$date = explode(" ", date('Y m d H i s', $unixtime));
$rewritereplace = array(
$date[0],
$date[1],
$date[2],
$date[3],
$date[4],
$date[5],
$post->post_name,
$post->ID,
$category,
$author,
$post->post_name,
$books_cat,
$books_subcat
);
$permalink = str_replace($rewritecode, $rewritereplace, $permalink);
}
else
{
}
return $permalink;
}
add_action('init', 'swi_post_type_books');
add_action('init', 'swi_custom_rewrite_post_type');
add_filter('post_type_link', 'swi_books_permalink', 10, 3);
?>
hope this help :) - 06/16/12 8:20pm
Daniel Yoen says:same code, better looks. :)
- 06/16/12 8:25pm
Daniel Yoen says:Sorry.
<?php
function swi_post_type_books()
{
register_post_type('books', array(
'labels' => array(
'name' => __('Books')
),
'public' => true,
'capability_type' => 'post',
'has_archive' => true,
'hierarchical' => false,
'query_var' => true,
'publicly_queryable' => true,
'query_var' => true,
'rewrite' => false
));
register_taxonomy('books_taxonomy', array(
'books'
), array(
'labels' => array(
'name' => __('Genre')
),
'show_ui' => true,
'hierarchical' => true,
'query_var' => true,
'rewrite' => false
));
}
function swi_custom_rewrite_post_type()
{
global $wp_rewrite;
add_rewrite_tag('%books_cat%', '([^/]+)');
add_rewrite_tag('%books_subcat%', '([^/]+)');
$books_structure = '/mybooks/%books_cat%/%books_subcat%/%books%';
$wp_rewrite->add_rewrite_tag("%books%", '([^/]+)', "books=");
$wp_rewrite->add_permastruct('books', $books_structure, false);
}
function swi_books_permalink($permalink, $post_id, $leavename)
{
$post = get_post($post_id);
$rewritecode = array(
'%year%',
'%monthnum%',
'%day%',
'%hour%',
'%minute%',
'%second%',
$leavename ? '' : '%postname%',
'%post_id%',
'%category%',
'%author%',
$leavename ? '' : '%pagename%',
'%books_cat%',
'%books_subcat%'
);
if ('' != $permalink && !in_array($post->post_status, array(
'draft',
'pending',
'auto-draft'
)))
{
$unixtime = strtotime($post->post_date);
$category = '';
if (strpos($permalink, '%category%') !== false)
{
$cats = get_the_category($post->ID);
if ($cats)
{
usort($cats, '_usort_terms_by_ID');
$category = $cats[0]->slug;
if ($parent = $cats[0]->parent)
$category = get_category_parents($parent, false, '/', true) . $category;
}
if (empty($category))
{
$default_category = get_category(get_option('default_category'));
$category = is_wp_error($default_category) ? '' : $default_category->slug;
}
}
$post_type = $post->post_type;
$books_cat = '';
$cat_parent = '';
if (strpos($permalink, '%books_cat') !== false)
{
$terms = wp_get_object_terms($post->ID, 'books_taxonomy');
if (!is_wp_error($terms) && !empty($terms))
{
foreach ($terms as $term)
{
if ($term->parent == 0)
{
$books_cat = $term->slug;
$cat_parent = $term->term_id;
break;
}
}
}
}
$books_subcat = '';
if (strpos($permalink, '%books_subcat%') !== false && !empty($cat_parent))
{
foreach ($terms as $term)
{
if ($term->parent == $cat_parent)
{
$books_subcat = $term->slug;
break;
}
}
}
$author = '';
if (strpos($permalink, '%author%') !== false)
{
$authordata = get_userdata($post->post_author);
$author = $authordata->user_nicename;
}
$date = explode(" ", date('Y m d H i s', $unixtime));
$rewritereplace = array(
$date[0],
$date[1],
$date[2],
$date[3],
$date[4],
$date[5],
$post->post_name,
$post->ID,
$category,
$author,
$post->post_name,
$books_cat,
$books_subcat
);
$permalink = str_replace($rewritecode, $rewritereplace, $permalink);
}
else
{
}
return $permalink;
}
add_action('init', 'swi_post_type_books');
add_action('init', 'swi_custom_rewrite_post_type');
add_filter('post_type_link', 'swi_books_permalink', 10, 3);
?>
- 06/16/12 9:49pm
mark says:Hey Daniel,
Wow, what a monster*... and a realy good start! :-) :-) :-)
- this code works perfectly for cpt posts with extactly two selected hierachical (sub)categories :-)
but...
- it doesn't work if only a maincategory is selected (or the category-depth is deeper then 2)
- it doesn't show archive-pages for links like
domain.com/mybooks/[book genre]/ --> archive of all book-articles matching 'book genre'
Any Ideas how we can achieve that? This last point is very important for me. Currently the homepage shows up when requesting an URL like "mysite.com/mybooks/sciencefiction/", but I'd like to see an achive-page of all scifi-books (shown by the matching template 'achive-books.php')
*) I removed all the unnecessary code and 'slimmed' it a little bit (still works like the code above):
function swi_post_type_books(){
register_post_type('books', array(
'labels' => array(
'name' => __('Books')
),
'public' => true,
'capability_type' => 'post',
'has_archive' => true,
'hierarchical' => false,
'query_var' => true,
'publicly_queryable' => true,
'query_var' => true,
'rewrite' => false
)
);
register_taxonomy('books_taxonomy', array('books'),
array(
'labels' => array(
'name' => __('Genre')
),
'show_ui' => true,
'hierarchical' => true,
'query_var' => true,
'rewrite' => false
)
);
}
function swi_custom_rewrite_post_type(){
global $wp_rewrite;
add_rewrite_tag('%books_cat%', '([^/]+)');
add_rewrite_tag('%books_subcat%', '([^/]+)');
$books_structure = '/mybooks/%books_cat%/%books_subcat%/%books%';
$wp_rewrite->add_rewrite_tag("%books%", '([^/]+)', "books=");
$wp_rewrite->add_permastruct('books', $books_structure, false);
}
function swi_books_permalink($permalink, $post_id, $leavename){
$post = get_post($post_id);
$rewritecode = array(
'%books_cat%',
'%books_subcat%'
);
if ('' != $permalink && !in_array($post->post_status, array('draft','pending','auto-draft'))){
$books_cat = '';
$cat_parent = '';
if (strpos($permalink, '%books_cat') !== false){
$terms = wp_get_object_terms($post->ID, 'books_taxonomy');
if (!is_wp_error($terms) && !empty($terms)) {
foreach ($terms as $term){
if ($term->parent == 0) {
$books_cat = $term->slug;
$cat_parent = $term->term_id;
break;
}
}
}
}
$books_subcat = '';
if (strpos($permalink, '%books_subcat%') !== false && !empty($cat_parent)){
foreach ($terms as $term){
if ($term->parent == $cat_parent){
$books_subcat = $term->slug;
break;
}
}
}
$rewritereplace = array(
$books_cat,
$books_subcat
);
$permalink = str_replace($rewritecode, $rewritereplace, $permalink);
}
return $permalink;
}
add_action('init', 'swi_post_type_books');
add_action('init', 'swi_custom_rewrite_post_type');
add_filter('post_type_link', 'swi_books_permalink', 10, 3);
I'll have to say: I had no idea that all this might be that complicated! :) - 06/17/12 9:56am
Daniel Yoen says:Hello, Try this :)
<?php
function swi_post_type_books()
{
register_post_type('books', array(
'labels' => array(
'name' => __('Books')
),
'public' => true,
'capability_type' => 'post',
'has_archive' => true,
'hierarchical' => true,
'query_var' => true,
'publicly_queryable' => true,
'query_var' => true,
'rewrite' => array('slug' => '/mybooks/%cat%/%subcat%', 'with_front' => true)
));
register_taxonomy('mybooks', array('books'
), array(
'labels' => array(
'name' => __('Genre')
),
'show_ui' => true,
'hierarchical' => true,
'query_var' => true,
'rewrite' => true
));
global $wp_rewrite;
add_rewrite_tag('%cat%', '([^/]+)');
add_rewrite_tag('%subcat%', '([^/]+)');
add_rewrite_tag("%books%", '([^/]+)', "books=");
$wp_rewrite->add_permastruct('books', '/mybooks/%cat%/%subcat%/%books%', false);
}
add_action('init', 'swi_post_type_books');
function swi_books_permalink($permalink, $post_id, $leavename)
{
$post = get_post($post_id);
$rewritecode = array('%cat%', '%subcat%');
if ('' != $permalink && !in_array($post->post_status, array('draft', 'pending', 'auto-draft')))
{
$post_type = $post->post_type;
$cat = '';
$cat_parent = '';
if (strpos($permalink, '%cat%') !== false)
{
$terms = wp_get_object_terms($post->ID, 'mybooks');
if (!is_wp_error($terms) && !empty($terms))
{
foreach ($terms as $term)
{
if ($term->parent == 0)
{
$cat = $term->slug;
$cat_parent = $term->term_id;
break;
}
}
}
}
$subcat = '';
if (strpos($permalink, '%subcat%') !== false && !empty($cat_parent))
{
foreach ($terms as $term)
{
if ($term->parent == $cat_parent)
{
$subcat = $term->slug;
break;
}
}
}
$rewritereplace = array($cat, $subcat);
$permalink = str_replace($rewritecode, $rewritereplace, $permalink);
}
else
{
}
return $permalink;
}
add_filter('post_type_link', 'swi_books_permalink', 10, 3);
function swi_rewrite_flush()
{
global $wp_rewrite;
$wp_rewrite->flush_rules();
}
add_action('init','swi_rewrite_flush');
?>
Hope this help :) - 06/17/12 2:44pm
mark says:Hey Daniel,
sorry to say, but: no effect :-/
The code isn't able to "decide" whether to call an archive OR an post...
As I read the php the book-permalink structure is still "static" (/mybooks/%cat%/%subcat%). So it works only if exactly 2 hierachical categories are selected:-(
I think we need somthing more flexible, maybe something completly different?
Hm... - 06/17/12 2:49pm
Daniel Yoen says:I've tested it and succeeded in wordpress 3.4
/mybooks/%cat%/%subcat%/%postname%/ | works
/mybooks/%cat%/ | works
In my view. :D - 06/17/12 3:56pm
mark says:hey Daniel,
I just send you an message with the live-example.. it realy doesn't work... :-( and if it would, I would wonder why?
I can't see a function/ section which could do what I've requested... maybe I'm wrong.. but could you please explain how an archive will be displayed by the code posted above? :-)
Thanks
:-)) - 06/20/12 5:31am
mark says:Hey Daniel,
thanks again. The new code works fine for me - no sub-(sub...)-categories, but I can live with that at the moment.
Thanks a lot!
Mark
- 06/16/12 8:19pm
This question has expired.
Daniel Yoen had additional discourse to offer.
Hai Bui, Arnav Joy, mark voted on this question.
Current status of this question: Completed
Warning: Please do not give out any FTP or ssh credentials to anyone, unless you trust them completely. Giving out login details is dangerous.
If the asker does not get an answer then they have 10 days to request a refund.
