4

I'd like to show 4 related posts (without a plugin) at the bottom of my blog. However, I want to exclude a certain category.

For example, if my blog post is in category 2 and 3, I want to ignore category 2 and only look for blog posts of category 3. Here is the relevant part of single.php:

Note: my code below is currently not working.

$related = get_posts( array(
    'category__in'  => wp_get_post_categories( $post->ID ),
    'numberposts'   => 4,
    'orderby'       => 'date',
    'post__not_in'  => array( $post->ID ),
    'cat'           => '-2'
) );

if( $related ) { 
    foreach( $related as $post ) {
        setup_postdata($post);
         /** .. **/
    }
}

Update: Category 2 is so prevalent that I want to ignore it in the search, but not hide those results.

For example, this post is in category 2 and 3. I want to find other posts with category 3, and maybe they have category 2, but I only want to search by category 3.

Update 2: I have this code below and I believe it is now working correctly:

$cat_ids = get_the_category();
if( ! empty( $cat_ids ) ) {
    $post_cat_ids = array();
    foreach( $cat_ids as $cat_id ) {
        if( $cat_id->cat_ID != 2 ) {
            $post_cat_ids[] = $cat_id->cat_ID;
        }
    }
}

$related = get_posts( array(
    'category__in' => wp_get_post_categories( $post->ID ),
    'numberposts' => 4,
    'orderby' => 'date',
    'exclude' => array( $post->ID ),
    'category' => $post_cat_ids
    ) );
  • I think what I need to do is remove category 2 from this line somehow wp_get_post_categories( $post->ID ) – Austin Feb 27 '17 at 17:41
  • You need to specify category__not_in => array( 2 ) – Nathan Johnson Feb 27 '17 at 17:42
2

What I could gather from your question is:

  1. You want to ignore one category (may be more) in the related post query.

  2. However, you don't want to actually exclude the posts from that category (in case any post belongs to that category, but also belongs to another category you want to look for).

Based on the assumption above, you may use the following CODE (some explanation is given within the CODE in comments):

    // set the category ID (or multiple category IDs)
    // you want to ignore in the following array
    $cats_to_ignore = array( 2 );
    $categories = wp_get_post_categories( get_the_ID() );
    $category_in = array_diff( $categories, $cats_to_ignore );
    // ignore only if we have any category left after ignoring
    if( count( $category_in ) == 0 ) {
        $category_in = $categories;
    }
    $cat_args = array(
        'category__in'   => $category_in,
        'posts_per_page' => 4,
        'orderby'        => 'date',
        'post__not_in'   => array( get_the_ID() )
        );
    $cat_query = new WP_Query( $cat_args );
    while ( $cat_query->have_posts() ) : $cat_query->the_post();
        /* just example markup for related posts */
        echo '<h2><a href="' . get_the_permalink() . '">' . get_the_title() . '</a></h2>';
    endwhile;
    // reset $post after custom loop ends (if you need the main loop after this point)
    wp_reset_postdata();

You cannot use 'cat' => '-2' or 'category__not_in' => array(2) because that will exclude all posts having category 2, even if those posts have other categories as well. So, instead of excluding, I've ignored the category 2 in the query with this CODE: array_diff( $categories, $cats_to_ignore );.

Note: I've used WP_Query instead of get_posts() because iteration with WP_Query looks more like the original loop. But of course you can use the get_posts() function as well, as it calls WP_Query internally anyway.

|improve this answer|||||
1

Give it a go to category__not_in parameter:

$related = get_posts( array(
    'numberposts'   => 4,
    'orderby'       => 'date',
    'category__in'  => wp_get_post_categories( $post->ID ),
    'category__not_in' => array(2);
) );

It should work.

Reference: https://codex.wordpress.org/Class_Reference/WP_Query#Category_Parameters

|improve this answer|||||
  • I tried this, but it hides all posts with category 2. Category 2 is so prevalent that I want to ignore it in the search but not hide those results. For example, this post is category 2 and 3. I want to find other posts with category 3, and maybe they have category 2, but I only want to search by category 3. – Austin Feb 27 '17 at 18:11
  • Yes, I tested it later, and it reproduced the same. Was wondering about using array_diff in this case, but then came here, saw Fayaz already did that perfectly. Cheers! – Rahul Arora Feb 28 '17 at 9:38
0
function custom_related_post()
{
    global $post;
    $related = get_posts(array('category__in' => wp_get_post_categories($post->ID), 'numberposts' => 2, 'post__not_in' => array($post->ID)));
    ?>
    <div class="related-post-content wow fadeInUp">
        <h5><?php esc_html_e('Related Posts', 'text-domain'); ?></h5>
        <div class="related-post d-flex">
            <?php
            if ($related) foreach ($related as $post) {
                setup_postdata($post);
                /* translators: used between list items, there is a space after the comma */

                ?>
                <div class="single-relatd-post">
                    <div class="img-overflow">
                        <a href="<?php the_title(); ?>"><?php the_post_thumbnail(); ?></a>
                    </div>
                    <h6><?php the_title(); ?></h6>
                    <p><?php the_author(); ?> <span>-</span> <?php echo get_the_date(); ?></p>
                </div>
                <?php wp_reset_postdata();
            }
            ?>
        </div>
    </div>

<?php }
|improve this answer|||||
0

Simply use

'category__not_in' => array( category id )

to exclude the posts from the specific category.

|improve this answer|||||
-1
$cat_ids = get_the_category();

if( ! empty( $cat_ids ) ) {
    $post_cat_ids = array();

    foreach( $cat_ids as $cat_id ) {
        if( 2 != $cat_id->cat_ID ) {
            $post_cat_ids[] = $cat_id->cat_ID;
        }
    }
}

$related = get_posts( array(
    'category__in'  => wp_get_post_categories( $post->ID ),
    'numberposts'   => 4,
    'orderby'       => 'date',
    'exclude'       => array( $post->ID ),
    'category'      => $post_cat_ids
) );
|improve this answer|||||
  • You are using category__in as well as category as argument, this is not necessary. Also, what if your $cat_ids have only one category (2) in a post? in that case $post_cat_ids will be empty array. Check out my answer for the corrections: wordpress.stackexchange.com/a/258168/110572 – Fayaz Feb 27 '17 at 19:55

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.