1

I have a foreach loop that prints out custom posts which uses a custom taxonomy. The user can then add whatever term/s they like to each post. This then prints out a list of terms on the custom template page; and links them all to a filter.

My issue is that when two posts contain the same term; it outputs/prints the term out twice. How can I solve this?

Here is a temporary example: http://website-test-lab.com/sites/zuludawn/video-archive/

Here is my full page template code:

<?php
// WP_Query arguments
$args = array (
    'post_type'          => 'cpt-video-arc',
    'posts_per_page' => '-1'
);

// The Query
$query = new WP_Query( $args );
?>

<div class="entry-content units-row group">

    <div class="category-list category-list-video-archive">
                Filter by tags:
                <button class="filter" data-filter="all">Show All</button>

                <?php $terms = array(); ?>

                <?php while ( $query->have_posts() ) : $query->the_post(); ?>

                    <?php $terms_tags = wp_get_post_terms( $query->post->ID, array( 'video-arc-tags-taxonomy' ) ); ?>

                    <?php foreach ( $terms_tags as $term_tag ) { ?>
                        <?php $terms[$term_tag->slug] = '<button class="filter" data-filter=".'.$term_tag->slug.'">'.$term_tag->name.'</button>'; ?>
                        <?php echo implode($terms,' '); ?>
                    <?php } ?>

                <?php endwhile; ?>

    </div><!-- .category-list -->

</div><!-- .entry-content -->

<?php wp_reset_postdata(); ?>
  • I think you are talking about terms, not taxonomies. video-arc-tags-taxonomy is the taxonomy, everyrhing below it is called terms :-) – Pieter Goosen May 26 '15 at 11:45
  • Yes, apologies. Updated the question. – Huw Rowlands May 26 '15 at 11:53
  • 1
    You should escape your output, if your terms name was </button><script>alert('hello');</script><button>... the esc_attr should fix that – Tom J Nowell May 26 '15 at 15:35
2

I would tend to do this:

$terms = array();
$terms_tags = wp_get_post_terms( $query->post->ID, array( 'post_tag' ) ); 
foreach ( $terms_tags as $term_tag ) {
  $terms[$term_tag->slug] = '<button class="filter" data-filter=".'.$term_tag->slug.',">'.$term_tag->name.'</button>';
}
echo implode($terms,', ');

It leverages the fact that PHP does not allow duplicate array keys, and thus avoids the overhead of function calls.

In your case, it should look like this (without all of that PHP tag spam):

$query = new WP_Query( $args ); ?>
<div class="entry-content units-row group">
  <div class="category-list category-list-video-archive">
    Filter by tags:
    <button class="filter" data-filter="all">Show All</button><?php 
    $terms = array(); 
    while ( $query->have_posts() ) : 
      $query->the_post();
      $terms_tags = wp_get_post_terms( $query->post->ID, array( 'video-arc-tags-taxonomy' ) );
      foreach ( $terms_tags as $term_tag ) { 
        $terms[$term_tag->slug] = '<button class="filter" data-filter=".'.$term_tag->slug.'">'.$term_tag->name.'</button>';  
      }
    endwhile; 
    echo implode($terms,' '); // this goes outside the while loop ?>
  </div><!-- .category-list -->
</div><!-- .entry-content -->
| improve this answer | |
  • I got distracted :) See the edit @ialocin – s_ha_dum May 26 '15 at 15:34
  • Thank you for the help but it has given me the same output I'm afraid. Duplicate terms. Note: I've added a temporary URL to the original question. – Huw Rowlands May 26 '15 at 18:30
  • There is something about the application that is unclear. This should work. Please add some detail to the question. Where and how is the code used? What is the context? – s_ha_dum May 26 '15 at 18:53
  • I've updated my original code above. It seems to only get the terms for the first post and not all of the others. – Huw Rowlands May 26 '15 at 19:01
  • 1
    As websupporter said, the $variable = array(); declaration has to be outside the while. @HuwRowlands – Nicolai May 26 '15 at 19:05
5

What about this:

<?php 
$already_used = array();
foreach ( $terms_tags as $term_tag ) : 
    if( ! in_array( $term_tag, $already_used ): ?>
        <button class="filter" data-filter=".<?php echo $term_tag->slug; ?>"><?php echo $term_tag->name; ?></button>
        <?php 
        $already_used[] = $term_tag; 
    endif;
 endforeach; 
?>

Explanation: You create an array, where you save which terms you've already used. If the current term is in this array, it will not be printed. Otherwise it will be printed and put into the array.

EDIT: You have to put the $already_used = array(); before the while ( $query->have_posts() ) of course.

| improve this answer | |

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.