Search code examples
phpwordpresspostforeachduplicates

For each loop results in duplicate post display when post has more than one category


I have the following code:

<div class="documents-posts">
    <?php if (!empty($posts)) : ?>
        <?php foreach ($posts as $post) : ?>
            <?php set_query_var( 'taxonomy', $taxonomy ); ?>
            <?php get_template_part('document'); ?>
        <?php endforeach; ?>
    <?php endif; ?>
</div>

which works fine as long as each post has only one category. When I assign a second category to a post the post is displayed twice. If I make it have 3 categories the post is displayed triple… Why?

Update: Declaration $posts variable

$post_type = 'press-release';
$taxonomy = 'press-release-types';
$categories = $xxxxxx->get_categories($taxonomy);
$posts = $xxxxxx->get_posts_ordered_by_categories($post_type, $taxonomy, $categories);

set_query_var( 'posts', $posts );
set_query_var( 'categories', $categories );
set_query_var( 'taxonomy', $taxonomy );

Update 2: From Helper php

public function get_posts_ordered_by_categories($post_type, $taxonomy, $categories) {
    $posts = [];
    foreach ($categories as $category) {
        $category_posts = $this->get_posts_from_category($post_type, $taxonomy, $category->term_id);
        $posts = array_merge($posts, $category_posts);
    }
    return $posts;
}

protected function get_posts_from_category($post_type, $taxonomy, $category_id) {
    return get_posts([
        'tax_query' => array(
            array(
                'taxonomy' => $taxonomy,
                'field'    => 'term_id',
                'terms'    => (int) $category_id,
            )
        ),
        'posts_per_page' => -1,
        'orderby' => 'date',
        'order' => 'DESC',
        'post_status' => 'publish',
        'post_type' => $post_type,
        'suppress_filters' => false,
    ]);
}

Solution

  • In get_posts_ordered_by_categories you're getting all posts from the category and put it in posts array. You have to check if post is existing in that array. For example:

    public function get_posts_ordered_by_categories($post_type, $taxonomy, $categories) {
        $posts = [];
        foreach ($categories as $category) {
            $category_posts = $this->get_posts_from_category($post_type, $taxonomy, $category->term_id);
            foreach ($category_posts as $post) {
                $posts[$post->ID] = $post;
            }
        }
        return $posts;
    }
    

    That way you'll get list of unique posts.