Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

Basically I want to achieve a glossary using custom post types and have some issues setting up rewrites the way I want them to be. I want it like that:

The main glossary URL: http://example.com/glossary/

Glossary terms starting with letter A: http://example.com/glossary/a/

The URL for a single glossary term: http://example.com/glossary/a/atomic/

I actually achieved this using the code below but I'm sure that it's a very awkward way to do it and I know it's malfunctioning somewhere as the wrong templates are called when viewing the pages. Except for http://example.com/glossary/, where archive-sumo-glossary-term.php gets called as expected, the other two just activate index.php in my theme.

Here goes (functions.php in the theme):

add_action('init', 'create_glossary');
function create_glossary()
{
    register_post_type
    (
        'sumo-glossary-term',
        array
        (
            'labels' => array
            (
                'name' => _x('Glossary Terms', 'post type general name'),
                'singular_name' => _x('Glossary Term', 'post type singular name')
                # And so on …
            ),
            'supports' => array('title', 'editor', 'thumbnail'),
            'public' => true,
            'rewrite' => array
            (
                'slug' => 'glossary',
                'with_front' => false

            ),
            'query_var' => 'glossary-term',
            'has_archive' => true
        )
    );

    register_taxonomy
    (
        'sumo-glossary-letter',
        'sumo-glossary-term',
        array
        (
            'hierarchical' => true,
            'labels' => array
            (
                'name' => _x('Letters', 'taxonomy general name'),
                'singular_name' => _x('Letter', 'taxonomy singular name')
                # And so one
            ),
            'show_ui' => true,
            'query_var' => 'glossary-letter',
            'rewrite' => false
        )
    );
}

add_filter('post_type_link', 'glossary_term_permalink', 10, 4);
function glossary_term_permalink($post_link, $post, $leavename, $sample)
{
    if ($post->post_type == 'sumo-glossary-term')
    {
        $permalink = str_replace('glossary/', 'glossary/' . $post->post_name[0] . '/', $post_link);
    }
    return $permalink;
}

add_rewrite_rule('^glossary/([^/]*)?$','index.php?glossary-letter=$matches[1]','top');
add_rewrite_rule('^glossary/([^/]*)/([^/]*)?$','index.php?glossary-term=$matches[2]','top');
share|improve this question
add comment

2 Answers

up vote 16 down vote accepted

You can always override the template that will be called with the template_include or a related filter, but this might hide deeper problems with custom archives.

As I understand it, you want to use the following structure:

  • /glossary/ should be an archive page for all sumo-glossary-term posts
  • /glossary/[letter]/ should be an archive page for posts with the taxonomy term [letter] in the sumo-glossary-letter taxonomy
  • /glossary/[letter]/[term-name]/ should be an individual sumo-glossary-term post

This means that the first will load the template archive-sumo-glossary-term.php, the second will load taxonomy-sumo-glossary-letter.php, and the third will load single-sumo-glossary-term.php.

I achieved this in WordPress 3.2 by explicitly setting the taxonomy rewrite slug, and both the rewrite slug and the archive slug for the post type, and no other rewrite rules. Also, I registered the taxonomy first and the post type after it, to make sure the priorities were right (otherwise a URL like /glossary/f/page/2 goes to glossary term page instead of page 2 of glossary letter f).

add_action('init', 'create_glossary');
function create_glossary()
{

    register_taxonomy
    (
        'sumo-glossary-letter',
        array(),
        array
        (
            'hierarchical' => true,
            'labels' => array
            (
                'name' => _x('Letters', 'taxonomy general name'),
                'singular_name' => _x('Letter', 'taxonomy singular name')
                # And so one
            ),
            'show_ui' => true,
            'query_var' => 'glossary-letter',
            'rewrite' => array(
                'slug' => 'glossary',
            ),
        )
    );

    register_post_type
    (
        'sumo-glossary-term',
        array
        (
            'labels' => array
            (
                'name' => _x('Glossary Terms', 'post type general name'),
                'singular_name' => _x('Glossary Term', 'post type singular name')
                # And so on …
            ),
            'supports' => array('title', 'editor', 'thumbnail'),
            'public' => true,
            'rewrite' => array
            (
                'slug' => 'glossary/%sumo-glossary-letter%',
                'with_front' => false

            ),
            'query_var' => 'glossary-term',
            'has_archive' => 'glossary',
            'taxonomies' => array( 'sumo-glossary-letter' ),
        )
    );
}

add_filter('post_type_link', 'glossary_term_permalink', 10, 4);
function glossary_term_permalink($post_link, $post, $leavename, $sample)
{
    if ( false !== strpos( $post_link, '%sumo-glossary-letter%' ) ) {
        $glossary_letter = get_the_terms( $post->ID, 'sumo-glossary-letter' );
        $post_link = str_replace( '%sumo-glossary-letter%', array_pop( $glossary_letter )->slug, $post_link );
    }
    return $post_link;
}
share|improve this answer
    
I'll try that tomorrow and see if it does the trick and get back here. Thanks! –  maryisdead Jul 9 '11 at 16:37
    
Ok, not exactly to tomorrow … It worked, almost perfectly! Thank you! What is not working is /glossary/. Gives me a 404 (archive-sumo-glossary-term.php is set up). Any ideas? Have to say that I'm stuck to WP 3.0.1 and it's maybe a version issue. Gotta test it again when I'm able to upgrade. Anyway, for the most part it's working and for now I don't necessarily need /glossary/ and just redirect to letter A. Thank you again! –  maryisdead Jul 16 '11 at 14:40
    
hey @maryisdead, I had the exact same issue and came up with the exact same solution, but was left with your exact same problem - how do you get /glossary to go to the archive-glossery.php template? I just found the answer - use 'has_archive' => 'glossary', instead of has_archive => true I just noticed Jan has it that way in his answer, but you don't have it that way in your original code - did you update that part? It started working for me as soon as I made that change –  Jeff Feb 9 '12 at 0:01
    
Hey Jeff! Yes, updated that part. Just checked again, still not working. The WordPress installation in question isn't still up-to-date (3.0.1) so maybe that's still the root of the problem. –  maryisdead Feb 11 '12 at 13:50
    
Same problem here, using WP 3.2.1. Still no solution? –  Richard B Mar 5 '12 at 15:42
show 1 more comment

I haven't personally used this, but what you may want to look at is "add_rewrite_rule"

http://codex.wordpress.org/Rewrite_API/add_rewrite_rule

also don't forget to save out permalinks once you've changed them.

share|improve this answer
    
I actually use add_rewrite_rule, just scroll my code to the bottom. :-) It's working fine so far, it's only that the wrong templates get called with this way of doing it. –  maryisdead Jun 30 '11 at 4:25
add comment

protected by toscho Jul 22 '12 at 16:52

Thank you for your interest in this question. Because it has attracted low-quality answers, posting an answer now requires 10 reputation on this site.

Would you like to answer one of these unanswered questions instead?

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