1

I'm trying to find a way to display related posts that are in a subcategory of a specific parent category based upon the subcategory of the current post. The current post may be assigned to multiple parent categories, but I only want to display related posts of one of the parent category's subcategories.

So for example, a post may be assigned to categories A, B and C, but I want to show related posts based upon the current post's B subcategory and not show all the posts from either A, B or C. Sorry, this question/problem is hard to explain.

I'm using this code to display the category name and posts, but I'm not sure how to exclude parent categories from it, so that only the subcategory posts will display.

More in 
    <?php $category = get_the_category(); 
        if ( in_category(52) || in_category(56) || in_category(57) || in_category(99) || in_category(28) ) {
            echo $category[1]->cat_name; 
        } else {echo $category[0]->cat_name;}
    ?>

<?php if (have_posts() && !(in_category('32'))) : ?>    
    <?php $i = 1; while (have_posts() && $i <= 1) : the_post(); ?>
        <?php $related = get_posts(array('category__in' => wp_get_post_categories($post->ID), 'numberposts' => 1, 'post__not_in' => array($post->ID)));
if($related) foreach( $related as $post) {
        setup_postdata($post); ?>
        <?php the_post_thumbnail('medium'); ?>
            <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
                <a href="<?php the_permalink(); ?>"><?php the_excerpt(''); ?></a>
                <?php the_author(); ?></div>    
            <?php } wp_reset_postdata(); ?>
    <?php $i++; endwhile; ?>
<?php endif; ?>

Thanks!

  • How do you choose which one of the "level 0" category you want to use to request sub-category of ? – Simon Nov 21 '13 at 15:15
  • @Simon in my case, the posts that I was trying to display may have belonged to several parent categories, but only to one subcategory of a specific parent category. I'm not sure how I would have displayed the related subcategory posts if posts were to have been in several parent categories and subcategories. Although I guess I could have just used the same method I used for the parent categories to exclude each subcategory that I did not want to display. There's probably a better way to do what I needed to do, but this is the best I could come up with and it's working for what I need. – Sean Henderson Nov 21 '13 at 16:05
2

There is indeed a much simpler way to do this.

First, to get the child category, just check the value of each category's parent. If it's a top-level category, the parent will be 0. So the child category will pass the test if( 0 != $category->parent ):

$categories = get_the_category();
foreach( $categories as $category ){
    if( 0 != $category->parent )
        $child_cat = $category;
}

Then query for your posts using that category ID as the cat argument. To output a thumbnail for only the first post, simply check if the current_post of your query object is 0. That number gets automatically incremented for each post in your loop, starting at 0:

if( isset( $child_cat ) ){  
    echo 'More in ' . $child_cat->name;
    $args = array(
        'cat' => $child_cat->term_id,
        'post__not_in' => array( get_the_ID() )
    );
    $related = new WP_Query( $args );
    if( $related->have_posts() ){
        while( $related->have_posts() ){
            $related->the_post();
            if( 0 == $related->current_post ){
                the_post_thumbnail('medium');
            }
            // your template tags, etc..
            the_title();
        }
        wp_reset_postdata();
    }
}

Also note, you never need to use wp_reset_query() unless you overwrite the global $wp_query, which doesn't happen here.

  • Milo thank you! That is definitely much simpler and more efficient than my code. Is there a way to change the style of the first post displayed in the loop? I want the first post title to be styled differently from the remaining post titles displayed below it, but I'm not sure how to style one title separately from the others within the same loop. Thanks again! – Sean Henderson Nov 21 '13 at 17:24
  • Look for the bit inside if( 0 == $related->current_post ){} where I have the_post_thumbnail, whatever is inside there will only be output on the first post. You could use that multiple times within the loop or make it an if/else to output different markup for first/everything else. – Milo Nov 21 '13 at 17:30
  • Excellent, thank you so much! This was a huge help. – Sean Henderson Nov 21 '13 at 17:38
0

So here's what I came up with. I don't think that this is the ideal way to code this, but it is doing exactly what I need it to.

This got me the label for the related items subcategory section in the sidebar by excluding the parent categories:

More in 
    <?php 
        $category = get_the_category();
        $catname = $category[0]->cat_name;
        if ($catname == 'News' || $catname == 'Featured' || $catname == 'Nav Bar News') {
            $catname = $category[1]->cat_name;
                if ($catname == 'News' || $catname == 'Featured' || $catname == 'Nav Bar News') {
                    $catname = $category[2]->cat_name;
                    if ($catname == 'News' || $catname == 'Featured' || $catname == 'Nav Bar News') {
                        $catname = $category[3]->cat_name;
                    }
                }
            } else {
                $catname = $category[0]->cat_name;
            }
            echo $catname;
        ?>

This is where it gets a little messy, but the code works for what I needed to achieve. I excluded the parent categories and then used the loop to display the posts from the related subcategory:

        wp_reset_query();
        $this_post = $post->ID;
        $category = get_the_category($post->ID);
        $category = $category[0]->cat_ID;
        if ($category == '30' || $category == '28' || $category == '99') {
            $category = $category[1]->cat_ID;
            if ($category == '30' || $category == '28' || $category == '99') {
                $category = $category[2]->cat_ID;
                if ($category == '30' || $category == '28' || $category == '99') {
                    $category = $category[3]->cat_ID;
                } 
            }
        } 
        $args = array(
            'category__in' => array($category),
            'post__not_in' => array($this_post)
        );
        $the_query = new WP_Query($args);

        if ( $the_query->have_posts() && !(in_category('32'))) {
            $i = 0; while ( $the_query->have_posts() && $i < 1) {
                $the_query->the_post(); ?>
                        <?php the_post_thumbnail('medium'); ?>
                        <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
                            <a href="<?php the_permalink(); ?>"><?php echo excerpt(30); ?></a>
                            <?php the_author(); ?>
            <?php $i++; } 
        } else {
            //echo 'no posts';
        }
        wp_reset_postdata();

        wp_reset_query();
        $this_post = $post->ID;
        $category = get_the_category($post->ID);
        $category = $category[0]->cat_ID;
        if ($category == '30' || $category == '28' || $category == '99') {
            $category = $category[1]->cat_ID;
            if ($category == '30' || $category == '28' || $category == '99') {
                $category = $category[2]->cat_ID;
                if ($category == '30' || $category == '28' || $category == '99') {
                    $category = $category[3]->cat_ID;
                } 
            }
        } 
        $args = array(
            'category__in' => array($category),
            'post__not_in' => array($this_post),
            'offset' => 1
        );
        $the_query = new WP_Query($args);

        if ( $the_query->have_posts() && !(in_category('32'))) {
            $i = 0; while ( $the_query->have_posts() && $i < 3) {
                $the_query->the_post(); ?>
                        <a href="<?php the_permalink() ?>" rel="bookmark" title="<?php the_title(); ?>"><?php the_title(); ?></a>
                    <?php if ($i < 2) { ?>
                        <hr style="width: 92%;">
                    <?php } ?>
            <?php $i++; } 
        } else {
            //echo 'no posts';
        }
        wp_reset_postdata();

I tried to do this all in one loop, but I couldn't figure out a way to display the featured image for only the first post and then exclude that post from being displayed again. If anyone has a cleaner way to write this, please let me know.

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.