Custom Post Type, Template Redirect the right way.

Okay, after reading many tutorials on how to create post types, I could not seem to find on that did the template redirect for my custom post types. But thanks to someone out there I was able to find what I needed to accomplish this. I’m sorry I don’t have a link to where I got this example, but kudos to him that help me solve it. There are two parts to this.

First we will need to setup the template redirect

add_action("template_redirect", 'template_redirect');
function template_redirect()
 {
 global $wp;

       $custom_post_types = array("portfolio");

 if (in_array($wp->query_vars["post_type"], $custom_post_types))
 {
       if ( is_robots() ) :
       do_action('do_robots');
       return;
 elseif ( is_feed() ) :
       do_feed();
       return;
 elseif ( is_trackback() ) :
       include( ABSPATH . 'wp-trackback.php' );
       return;
 elseif($wp->query_vars["name"]):
       include(TEMPLATEPATH . "/single-".$wp->query_vars["post_type"].".php");
       die();
 else:
       include(TEMPLATEPATH . "/".$wp->query_vars["post_type"].".php");
       die();
 endif;

 }
 }

Second we will need to add a rewrite rule to wordpress to do the redirecting properly.

add_new_rules()
function add_new_rules(){

 global $wp_rewrite;

 $rewrite_rules = $wp_rewrite->generate_rewrite_rules('custom_post_type/');
 $rewrite_rules['custom_post_type/?$'] = 'index.php?paged=1';

 foreach($rewrite_rules as $regex => $redirect)
 {
       if(strpos($redirect, 'attachment=') === false)
       {
       $redirect .= '&post_type=custom_post_type';
       }
       if(0 < preg_match_all('@\$([0-9])@', $redirect, $matches))
       {
             for($i = 0; $i < count($matches[0]); $i++)
             {
                   $redirect = str_replace($matches[0][$i], '$matches['.$matches[1][$i].']', $redirect);
             }
       }
       $wp_rewrite->add_rule($regex, $redirect, 'top');
 }

 }

Adding these two functions to you custom post type class will enable you to create listing page (like index.php) ‘custom_post_type’.php and a single-’custom_post_type’.php. Doing so will already create the query for that post type, so all you have to do is create the loop as you normally would and go to town formatting your custom post type with easy.

13 Responses to “Custom Post Type, Template Redirect the right way.”

  1. Anonymous says:

    Thank you, this is just what I needed. I spent hours trying to figure how to do this an other posts didn’t quite help my. Thanks

  2. Frank says:

    Please can you more write about your second function add_new_rules() – how works this, it is important to change the type in the source to the own custom post type and hwo inlcude this function in WP, maybe a hook?
    Thanks for your time!

    • Yes, everywhere you see ‘custom_post_type’ you would change to you custom post type. With this function you don’t need to use a hook. I generally would run this function in the constructor function of my custom post type class. It would come after the register post type function as such $this->add_new_rules(); Not too difficult.

  3. Jacob says:

    Thanks for this. It’s working great for my first post type, but if I copy/paste it again changing the post_type it gives errors when I try to load my site. Is it possible to add more than one post type redirect with one code?

    • Yes, if you create an array of custom post types as such:

      $array_of_post_types = array("", "","");

      The run a foreach loop on the array you could accomplish that task.

      So your code would look similar to this:

      function add_new_rules()
      	{
      		global $wp_rewrite;
      
      		$array_of_post_types = array("custom_type01", "custom_type02","custom_type03");
      
      		foreach($array_of_post_types as $type)
      		{
      
      			$rewrite_rules = $wp_rewrite->generate_rewrite_rules($type.'/');
      			$rewrite_rules[$type.'/?$'] = 'index.php?paged=1';
      
      			foreach($rewrite_rules as $regex => $redirect)
      			{
      			   if(strpos($redirect, 'attachment=') === false)
      			   {
      			   $redirect .= '&post_type='.$type;
      			   }
      			   if(0 < preg_match_all('@\$([0-9])@', $redirect, $matches))
      			   {
      					 for($i = 0; $i < count($matches[0]); $i++)
      					 {
      						   $redirect = str_replace($matches[0][$i], '$matches['.$matches[1][$i].']', $redirect);
      					 }
      			   }
      			   $wp_rewrite->add_rule($regex, $redirect, 'top');
      			}
      		}
      
      	}
      
  4. Mariano says:

    Instead of this:

    $array_of_post_types = array("custom_type01", "custom_type02","custom_type03");

    You could use this:

    $array_of_post_types = array_splice( get_post_types( array( 'exclude_from_search' => false ), 'names' ), 3 );

    You will define the template_redirect and add_new_rules only once for ALL the custom types you may have.

  5. Came across your web site via msn the other day and absolutely love it. Carry on the excellent work.

  6. Great, I never knew this, thanks.

Leave a Reply

Project Details