Get Related Posts For Custom Post Type By Category

This code will get the related posts of the current custom-post-type single post being viewed. This will get posts only of the same custom post type and the same category of the current single post. Obviously, this only works for your custom post type if you gave it support for ‘category’ when you registered it.

Use this code on the sidebar of single.php, or on single-custom_post_type.php. Use it to show a custom loop of related items on the sidebar or footer of the current single custom post.

Note: this code is only necessary for getting related posts by category of custom post types. For related posts by category of regular posts, see Related Posts By Category. Or, for related posts by custom taxonomy, rather than category, see Get Related Posts For Custom Post Type by Custom Taxonomy.

	<!-- begin custom related loop, isa -->

		<?php
		// get the custom post type's taxonomy terms
		 
		$custom_taxterms = wp_get_object_terms( $post->ID, 'category', array('fields' => 'ids') );

		$args = array(
			'post_type' => 'YOUR_CUSTOM_POST_TYPE',
			'post_status' => 'publish',
			'posts_per_page' => 3, // you may edit this number
			'orderby' => 'rand',
			'post__not_in' => array ( $post->ID ),
			'tax_query' => array(
			    array(
			        'taxonomy' => 'category',
			        'field' => 'id',
			        'terms' => $custom_taxterms
			    )
			)
		);
		$related_items = new WP_Query( $args );
		// loop over query
		if ( $related_items->have_posts() ) : ?>

			<li class="widget widget_categories">
			<h3 class="widget-title">Similar Posts</h3>
			<ul>

			<?php while ( $related_items->have_posts() ) : $related_items->the_post(); ?>
		    
		    	<li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>

			<?php endwhile; ?>

			</ul>
			</li>

		<?php endif;
		// Reset Post Data
		wp_reset_postdata();
		?> 
 
<!-- end custom related loop, isa -->

For this loop to work for you, you must make the following change to the code:

On line 9: change YOUR_CUSTOM_POST_TYPE to the name of you custom post type. Leave in the single quotes.

You may optionally edit the HTML on lines 26–28, 32, 36, and 37. If left as is, it will show a list of 3 related posts. To show a different number of posts, you can change the “3” on line 11 to whatever number you need.

See more: , ,

We've 27 Responses

  1. February 11th, 2013 at 3:38 pm

    Hello,

    I’m french so excuse me for my very bad english !!!
    Thanks for this code, it’s very usefull for me !
    I just have one problem, the instruction ‘orderby’ doesn’t work, i try ‘ASC’, ‘DESC’, ‘ID’… but it’s always by DESC…
    Do you have an idea for me ?

    thank you very much from France !

    Helene
    • February 11th, 2013 at 4:45 pm

      Use ‘order‘, not ‘orderby’ to specify ‘ASC’ or ‘DESC’.
      ‘Orderby’ is to specify whether it will be by one of the following:
      ‘ID’
      ‘author’
      ‘title’
      ‘name’
      ‘date’
      ‘rand’, etc..

      Then ‘order’ either ‘ASC’ or ‘DESC’.
      Example:

      'orderby' => 'name',
      'order' => 'ASC',
      

      Another:

      'orderby' => 'date',
      'order' => 'DESC',
      

      Merci pour votre question. 🙂

      Isabel
  2. February 12th, 2013 at 1:45 am

    thanks for your reply

    i try this but it’s doesn’t work :

    $args = array(
    ‘post_type’ => ‘portfolio’,
    ‘posts_per_page’ => -1,
    ‘order’ => ‘date’,
    ‘orderby’ => ‘ASC’,
    ‘tax_query’ => array(
    array(
    ‘taxonomy’ => ‘albums’,
    ‘field’ => ‘id’,
    ‘terms’ => $custom_taxterms
    )
    )
    );

    Helene
    • February 12th, 2013 at 9:36 am

      You have ‘order’ and ‘orderby’ mixed up. You have:

      ‘order’ => ‘date’,
      ‘orderby’ => ‘ASC’,

      Switch it to:

      ‘orderby’ => ‘date’,
      ‘order’ => ‘ASC’,
      
      Isabel
  3. Pingback: Get Related Posts For Custom Post Type by Custom Taxonomy

  4. May 15th, 2013 at 6:17 pm

    Great tool.
    I need to add pagination to the related post
    previous_posts_link();
    next_posts_link();
    But can make it work.
    Any advice?
    Thanks in advance
    Daniel

    Daniel Viera
    • May 15th, 2013 at 7:19 pm

      Thank you. If you mean on a single post, then use
      previous_post_link();
      next_post_link();

      Almost the same thing you have, but without the ‘s’ at the end of `post`. Hope it helps.

      Isabel
      • May 15th, 2013 at 7:26 pm

        Thanks Isabel for your fast response.
        But I don’t need the prev or next link for the single post.
        I have a lot of related posts, and I want to display only 9 of them per page, but be able to navigate to the next, or previous set of 9 “related post”, while viewing a single post.
        I hope I could explain well, excuse my english, I speak spanish.
        Best Regards
        Daniel

        Daniel Viera
  5. July 5th, 2013 at 9:15 am

    Hi Isabel. I tried one of your other codes for getting related custom posts with custom taxonomy and it worked perfectly. Now I’d like to get all the custom posts regardless of it’s taxonomy, so I think this code might be the way to go. However, I don’t know what you mean by “Obviously, this only works for your custom post type if you gave it support for ‘category’ when you registered it”

    Thanks for the awesome codes and your work.

    Carlos
  6. July 5th, 2013 at 3:14 pm

    Your welcome. If you want all posts of a custom post type, this is probably isn’t what you need, because this filters them by the post type’s category. This code only works if you assign categories to the custom posts.

    So to answer your question:

    When you register the post type, which should look something like this:

    $args = array(
    
        // bunch of arguments here
    
          ); 
    
    register_post_type( 'your_custom_posttype', $args );

    You must add this to the array of arguments in the $args:

    'taxonomies' => array('category'),
    

    That will let you assign categories to your custom post types.

    Isabel
      • July 8th, 2013 at 2:02 am

        Right, you don’t need to filter by cat or taxonomy. This should work:

        This gets all posts of the “projects” post type:

        $my_query = new WP_Query('post_type=projects&posts_per_page=-1');
              while ($my_query->have_posts()) : $my_query->the_post();
        
                  // OUTPUT HTML HERE
                  if ( has_post_thumbnail() ) {
                        the_post_thumbnail();
                   } 
        
             endwhile;  
        wp_reset_query();
        
        Isabel
  7. July 10th, 2013 at 11:51 am

    I’ve tried this, and it looks like a neat, clean solution. But it doesn’t seem to be filtering by term for me. Any advice?

    Anderson Multimedia
  8. September 29th, 2014 at 3:49 am

    Hi, Isabel. Is there a way to use this for a page? I have a page that has the same slug as the category slug. I want to be able to use the page’s slug to pull in all posts from that specific category.

    Dwaynne
    • September 29th, 2014 at 11:18 am

      For that, you’d have to create a custom page template for that page. You can do this by copying your theme’s page.php into a new file. Name it page-slug.php in which “slug” is the page’s slug. Paste this header at the very top of it:

      <?php
      /*
      Template Name: Custom Template Name
      */
      ?>
      

      See this for more info on custom page templates.

      Then, to display only posts that have your desired category, first find the loop, which begins with something like this:

      <?php if (have_posts()) : while (have_posts()) : the_post();?>
      

      and ends with something like this:

      <?php 
      endwhile; 
      endif; 
      ?>
      

      And replace the entire loop with this:

      <?php
      /**
      * Display posts that have your desired category
      */
      
      $paged = ( get_query_var('paged') ) ? get_query_var('paged') : 1;
      
      // The Query
      $my_query = new WP_Query( 
      							array(
      									'paged'					=> $paged,
      									'posts_per_page'	=> 10,
      									'cat'						=> 13
      									)
      );
      
      
      // The Loop
      if ( $my_query->have_posts() ) {
      	echo '<ul>';
      	while ( $my_query->have_posts() ) {
      		$my_query->the_post();
      		
      		
      		<li>
      		<a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>">
      		<?php the_title(); ?>
      		</a>
      		</li>		
      		
      	}
      	
      	
      	echo '</ul>';
      } else {
      	
      	// no posts found
      	
      }
      
      // Restore original Post Data
      wp_reset_postdata();
      ?>
      

      Replace the 13, on line 13 above, with your desired category ID.
      Hope that helps.

      Isabel
    • August 24th, 2015 at 11:07 pm

      Actually it works as well with tax_query if i change the first letter to the capital one, so Tax_query, but still the post appers, really weird, waiting for some solution.Cheers

      Max
  9. August 24th, 2015 at 11:18 pm

    Found a solution. If anyone is having the same issues (under related post it appears the one on which you are) move out

    
    'post__not_in' => array ($post->ID),
    
    

    from Tax_query and place it above under $args

    Max
    • March 9th, 2017 at 1:05 am

      You can use it as a function by copying lines 6–41 and paste theme here into line 5:

      function isa_custom_related_posts() {
      	global $post;
      
      	// Copy lines 6--41 and paste theme here
      
      }
      

      And then you would display the related posts by using this template tag inside a theme (or child theme’s) template file:

      <?php isa_custom_related_posts(); ?>
      Isabel
  10. April 14th, 2017 at 12:48 pm

    Hello, I am using your code to display Jury members based on the year that is selected (juryyear). Within that year it will list all jury members with their categories assign to them jury_category. Is there away I can sort jury_category alphabetically? As of right now it is listing the category based off the jury order.

    <?php 
    			$custom_taxterms = wp_get_object_terms( $post->ID, 'juryyear', array('fields' => 'ids') );
    			$args = array(
    				'post_type' 		=> $current_post->post_type,
    				'posts_per_page' 	=> 99,
    				
    				'tax_query' 		=> array(
    					array(
    						'taxonomy' 	=> 'juryyear',
    						'field' 	=> 'id',
    						'terms' 	=> $custom_taxterms,
    				'cat'            =>  $category_id
    					)
    				),
    				//'post__not_in' => array ($post->ID),
    			);
    			$related_items = new WP_Query( $args );
    			if ($related_items->have_posts()) :
    			echo '<ul>';
    			while ( $related_items->have_posts() ) : $related_items->the_post();
    		?>
    		<?php
    			$media_attrs = wp_get_post_terms( $post->ID, 'jury_category', 
    				array(
    					'orderby' 	=> 'title',
           				'order' 	=> 'ASC'
    			) );
    			if (!empty($media_attrs)){ 
    			foreach($media_attrs as $attr){
    			echo '<li><a href="' .get_permalink( $post->ID ).'">';
    			echo $attr->name  . '</li></a>';}    
    		?>
    		<?php } ?>
    		<?php endwhile; echo '</ul>'; endif; wp_reset_postdata();?>
    
    Anthony
    • April 17th, 2017 at 2:27 pm

      You can do this by changing your line 25 from 'orderby' => 'title', to 'orderby' => 'name',. This should work since the terms use “name” instead of “title” for the title field. Hope that helps.

      Isabel

Questions and Comments are Welcome

Your email address will not be published. All comments will be moderated.

Please wrap code in "code" bracket tags like this:

[code]

YOUR CODE HERE 

[/code]