1

I have a custom post type and two custom taxonomies associated with it. One is locations and the other is activities. How can I form the permalinks in the following format?

http://mysite.com/usa/diving

Therefore the first one would be the location taxonomy and second would be the activity taxonomy?

  • if the url can be something like http://mysite.com/usa/activity/diving it will be a lot simpler... – gmazzap Aug 21 '13 at 17:35
  • how will WordPress know you want taxonomy terms instead of a page named usa with a subpage named diving? – Milo Aug 21 '13 at 17:42
  • Only way is get all terms for both taxonomies on every request, compare them with the url parts and if they match do the work. But this: 1) will slow down the site a lot 2) in case of collisions (one pointed out my @milo) the 'default' request never go successfull. – gmazzap Aug 21 '13 at 17:53
  • I think I've been trying to go down a close ended road. Probably easier to create a page with a custom query that fetches what I want. Thanks for clarifying. – urok93 Aug 22 '13 at 21:47
  • Take a look here: wordpress.stackexchange.com/questions/11582/…; and here: wordpress.stackexchange.com/questions/5308/… - good luck! – Nicolai Aug 23 '13 at 9:57
2

I recently talked about this at a couple of WordCamps. Here's my talk from WC Portland, and the slides, source code, etc. Check out Recipe #2 specifically.

First off, you should probably have a static prefix to start the URLs. It's not 100% necessary, but without it your rewrite will conflict with page permalinks. If you decide to use the static prefix, you might want to make it about the post type, since that's what your taxonomies organize. I don't know what that is, so I'm making a guess that it's about "guides." In that case, your URIs would be something like /guides/usa/diving/.

Here's some code to get you started. If anything doesn't make sense to you, you should watch the presentation and follow along with the slides.

<?php

/**
 * Setup custom permalinks with multiple taxonomies
 */

if ( !class_exists( 'WPSE_110508' ) ) :

class WPSE_110508 {

    private static $instance;

    public static function instance() {
        if ( ! isset( self::$instance ) ) {
            self::$instance = new WPSE_110508;
            self::$instance->setup();
        }
        return self::$instance;
    }

    public function setup() {
        add_action( 'init', array( $this, 'structures' ) );
        add_filter( 'post_type_link', array( $this, 'post_type_link' ), 10, 2 );
        add_filter( 'term_link', array( $this, 'term_link' ), 10, 3 );
    }

    /**
     * Register our data structures
     *
     * @return void
     */
    function structures() {
        register_taxonomy( 'location', 'guide', array(
            'label' => 'Body Types',
            'rewrite' => array( 'slug' => 'guides' )
        ) );

        add_permastruct( "all_activities", "guides/all/%activity%" );
        register_taxonomy( 'activity', 'guide', array(
            'label' => 'Activities',
            'rewrite' => array( 'slug' => 'guides/%location%' )
        ) );

        register_post_type( 'guide', array(
            'public' => true,
            'label' => 'Guides',
            'rewrite' => array( 'slug' => 'guides/%location%/%activity%' )
        ) );
    }


    /**
     * Filter post type links for guides to replace %location% & %activity% if present
     *
     * @param string $link
     * @param object $post
     * @return string
     */
    function post_type_link( $link, $post ) {
        if ( 'guide' == $post->post_type ) {
            if ( $locations = get_the_terms( $post->ID, 'location' ) ) {
                $link = str_replace( '%location%', array_pop( $locations )->slug, $link );
            }
            if ( $activities = get_the_terms( $post->ID, 'activity' ) ) {
                $link = str_replace( '%activity%', array_pop( $activities )->slug, $link );
            }
        }
        return $link;
    }


    /**
     * Filter term links for activities to replace %location% with "all"
     *
     * @param string $termlink
     * @param object $term
     * @param string $taxonomy
     * @return string
     */
    function term_link( $termlink, $term, $taxonomy ) {
        if ( 'activity' == $taxonomy ) {
            return str_replace( '%location%', 'all', $termlink );
        }
        return $termlink;
    }

}

function WPSE_110508() {
    return WPSE_110508::instance();
}
add_action( 'after_setup_theme', 'WPSE_110508' );

endif;
1

It seems you're using two non-hierarchical custom taxonomies. Try using a single hierarchical custom taxonomy (imagine how categories work). That way your URLs would be able to look like "usa/diving".

When you register your custom taxonomy via your theme's functions.php, do something like this:

'hierarchical' => true,
1

The .php function is this <?php get_term_link( $term, $taxonomy ); ?> and here you have an example of how you can use this into your code: $terms = get_terms('species');

echo '<ul>';
foreach ($terms as $term) {
    //Always check if it's an error before continuing. get_term_link() can be finicky sometimes
    $term_link = get_term_link( $term, 'species' );
    if( is_wp_error( $term_link ) )
        continue;
    //We successfully got a link. Print it out.
    echo '<li><a href="' . $term_link . '">' . $term->name . '</a></li>';
}
echo '</ul>';
0

It seems as though you actually have multiple options here.

Good luck!

  • 1
    I would also recommend the first one, Custom Permalinks. – Ciprian Aug 26 '13 at 13:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.