WordPress.org

Ready to get started?Download WordPress

Forums

Two templates + permalinks for the same post (different "views") (7 posts)

  1. thornomad
    Member
    Posted 2 years ago #

    I feel like I read about how to accomplish this using template_redirect but can't, for the life of me, find it. Hoping someone can help.

    I am trying to use two separate permalinks/templates for a single post - each providing different views of the post (through different templates).

    For example:

    http://example.com/category/post-name          -> uses template1.php
    http://example.com/category/post-name/details  -> uses template2.php

    Both refer to the same post ID but will show a different layout. I have a lot of custom field data that I want to display under details but not under the default view.

    Thanks in advance,
    Damon

  2. Eddie Moya
    Member
    Posted 2 years ago #

    You should probably not use template_redirect because it can blow away everything else that WordPress does with the Template Hierarchy - its called right at the beginning of template-loader.php. Also, it mean you need to include the template yourself in some way or another, which is kind of annoying.

    Looks like your targeting single posts. I take it that /category/ in your example permalinks actually refers to /category-name/, not the /category/ base that is required for category indexes.

    Since your targeting single posts, its best to filter 'single_template'. Optionally you can check for post type, since single templates can be pages or posts, and you may not want that.

    You have a second problem though, and its actually more complicated. The /details bit at the end of your url won't be captured. The rewrite rules are going to be confused by it and throw a 404 at you. So to capture that your going to need to add something to the rewrite rules. Try this, I tested this a little and it seems to work.

    function detail_rewrite_rule( $rules ) {
        $newrules = array();
        $newrules['(.+?)/([^/]+)(/[0-9]+)?/detail/?$'] = 'index.php?category_name=$matches[1]&name=$matches[2]&page=$matches[3]&detail=1'; 
    
        return $newrules + $rules;
    }
    add_filter( 'rewrite_rules_array','detail_rewrite_rules' );
    
    function detail_flush_rules(){
    	$rules = get_option( 'rewrite_rules' );
    
    	if ( ! isset( $rules['(.+?)/([^/]+)(/[0-9]+)?/detail/?$'] )   ) {
    
    		global $wp_rewrite;
    	   	$wp_rewrite->flush_rules();
    	}
    }
    add_action( 'init','detail_flush_rules' );

    That should extend your permalink structure to allow you to add 'detail' to the query string and give it a value of '1'. Which we can then check for when filtering the template.

    function filter_single_template($template){
        $object = get_queried_object();
        $templates = array();
    
        /* If detail is in the query string, create a list of templates to use */
        if($_GET['detail']) {
            $templates[] = "detail-single.php";
            $templates[] = "detail-single-{$object->post_type}.php";
        }
    
        /* If one of our custom detail templates exists, return it.
         * Otherwise return the original template
         */
        return (!empty(locate_template($templates))) ? locate_template($templates) : $template;
    }
    add_filter('page_template', 'filter_single_template');

    What were doing here is checking to see if $_GET['detail'] is true, and if it is, were creating a hierarchical list of templates to use - if they exist. The locate_template function will look through the list from top to bottom and return the path to the first one it finds. Later, we check to see if locate_template() found anything at all, if not, we keep the original template which might be single-{post_type}.php, single.php, or index.php.

    By doing it this way, you not only preserve the original Template Hierarchy, you are actually extending it.

  3. thornomad
    Member
    Posted 2 years ago #

    Wow - thank you so much for this detailed post. I'm going to be away for a few days so I won't have time to test it until after the weekend. But it looks like you've solved my problem! I just need to implement it. And thank you for that advice.

  4. Eddie Moya
    Member
    Posted 2 years ago #

    Not a problem, I actually had similar bits of this already done.

    Just changed the rewrite rule to say detail, and to a boolean, instead of what I had it set to do - and then I already do a bunch of template redirection since I built the Category Templare Hierarchy plugin, just needed to change some stuff around to capture and check for detail in the query string (test the crap out of that btw).

    Let me know how this all works out.

  5. ctaalliance
    Member
    Posted 2 years ago #

    The above (first bit of functions, more specifically) wouldn't work without another function to open up a qvar:

    function detail_queryvars( $qvars ) {
      $qvars[] = 'detail';
      return $qvars;
    }
    add_filter('query_vars', 'detail_queryvars' );

    Maybe this was a version difference or maybe 'detail' was already opened up. Extremely frustrating to figure out. Hope this saves you some brain cells!

  6. ctaalliance
    Member
    Posted 2 years ago #

    Also, referencing $_GET didn't work. Had to do this:

    global $wp_query;
    if ( $wp_query->query_vars['detail'] ) { ...
  7. Eddie Moya
    Member
    Posted 2 years ago #

    ctaaliance is absolutely right on both counts. My apologies for leaving that stuff out.

    You dont always have to globalize $wp_query though. Most cases I think you can use the get_query_var() function.

    if( get_query_var('detail') ) { ...

    Sorry for the confusion.

Topic Closed

This topic has been closed to new replies.

About this Topic