Problem (Example): I have one custom taxonomy called "portfolios". It is tied to a custom post type called "portfolio". I create a portfolios term called Animals and another called Pets. Then I create a portfolio post called Beagle that belongs to both portfolios terms. In their respective term archives, Beagle is displayed as expected.
Question: The permalink for the Beagle post is always http://example.com/portfolios/animals/beagle
, irrespective of the taconomy term archive (animals or pets) in which it is being displayed. How can I make the permalink reflect the term of the current archive page?
In other words, I need http://example.com/portfolios/animals/beagle
to be the permalink on the "animals" archive and http://example.com/portfolios/pets/beagle
to be the permalink on the pets archive - and they both send you to the same post "Beagles".
Note: This also affects how the Prev/Next links within the post will function (more on that later).
Here is the code I have so far:
add_action( 'init', 'portfolio_post' );
function portfolio_post()
{
$labels = array(
'name' => _x('Portfolio Items', 'post type general name'),
/* The rest of the labels, right out of the codex */
);
$args = array(
'labels' => $labels,
'public' => true,
'exclude_from_search' => false,
'publicly_queryable' => true,
'show_ui' => true,
'show_in_nav_menus' => true,
'show_in_menu' => true,
'show_in_admin_bar' => true,
'menu_position' => 5,
'menu_icon' => get_stylesheet_directory_uri() . '/images/portfolio-icon16.png',
'capability_type' => 'post',
'hierarchical' => false,
'supports' => array('title','editor','page-attributes','thumbnail','revisions'),
'taxonomies' => array('portfolios'),
'has_archive' => 'portfolios',
'rewrite' => array('slug' => 'portfolios/%portfolios%'),
'query_var' => true
);
register_post_type('portfolio',$args);
}
/* Register the "Portfolios" Taxonomy */
add_action( 'init', 'portfolios_taxonomy', 0 );
function portfolios_taxonomy() {
$labels = array(
'name' => _x('Portfolios', 'taxonomy general name'),
/* The rest of the labels, right out of the codex */
);
$args = array(
'labels' => $labels,
'public' => true,
'show_ui' => true,
'show_in_nav_menus' => true,
'show_admin_column' => true,
'hierarchical' => true,
'query_var' => true,
'rewrite' => array('slug' => 'portfolios'),
);
register_taxonomy('portfolios', array('portfolio'), $args);
}
add_filter('post_type_link', 'portfolio_permalink_filter_function', 1, 3);
function portfolio_permalink_filter_function( $post_link, $id = 0, $leavename = FALSE ) {
if ( strpos('%portfolios%', $post_link) === 'FALSE' ) {
return $post_link;
}
$post = get_post($id);
if ( !is_object($post) || $post->post_type != 'portfolio' ) {
return $post_link;
}
$terms = wp_get_object_terms($post->ID, 'portfolios');
if ( !$terms ) {
return str_replace('portfolios/%portfolios%/', '', $post_link);
}
return str_replace('%portfolios%', $terms[0]->slug, $post_link);
}
The following URLs do what they are supposed to do:
http://example.com/portfolios
<-- portfolio archive (archive-portfolio.php)
http://example.com/portfolios/animals/
<-- term archive (taxonomy-portfolios.php)
http://example.com/portfolios/pets/
<-- term archive (taxonomy-portfolios.php)
http://example.com/portfolios/animals/beagle
<-- post (single-portfolio.php)
However, making http://example.com/portfolios/animals/beagle
= http://example.com/portfolios/pets/beagle
continues to elude me.
Post Prev/Next Links
If you are navigating through posts in the "Pets" archive using the prev/next links at the bottom of the posts, when you get to the "Beagle" post, the prev/next links now display the previous and next links to posts in the "Animals" archive (because of the way I generate the prev/next links and because the Beagle permailnk term is "animals"). Here is the code for the prev/next links:
/* Previous/Next Links within primary parent portfolios taxonomy term */
$post_ids = get_posts(array(
'numberposts' => -1, // get all posts.
'post_type' => 'portfolio',
'fields' => 'ids', // Only get post IDs
'tax_query' => array(array('taxonomy' => 'portfolios', 'field' => 'name', 'terms' => $portfolio_terms[0])),
'orderby' => 'title',
'order' => 'ASC'
));
$thisindex = array_search($post->ID, $post_ids);
$previd = $post_ids[$thisindex-1];
$nextid = $post_ids[$thisindex+1];
echo '<div class="post-prev-next"><!-- .post-prev-next -->';
if ( !empty($previd) ) {
echo '<div class="post-prev"><a rel="prev" href="' . get_permalink($previd) . '" title="'. get_the_title($previd) .'">« '. get_the_title($previd) .'</a></div>';
}
if ( !empty($nextid) ) {
echo '<div class="post-next"><a rel="next" href="' . get_permalink($nextid) . '" title="'. get_the_title($nextid) .'">'. get_the_title($nextid) .' »</a></div>';
}
echo '</div><!-- end .post-prev-next -->';
The logic above will likely have to change once the first problem is solved, but I'm not sure what it should change to.
It looks like @TheDeadMedic hinted at a solution on this answer, but since the questioner was not going in that direction, it was never elaborated upon.
If you're assigning multiple categories to a single product, I can easily change how it determines which one to use in the permalink.
Thanks to reading tons of stackexchange Q/A's and some tutorial blogs over the past few days, I was able piece together what I have so far, but I've hit a wall with this problem. I appreciate any help the community can provide.