I'm trying to display a custom post type archive page which displays all the articles of a a custom post type in columns. The columns organize them in their assigned category.

On the main page, I do this successfully with regular posts. I loop thru each category, generate a column, and then loop thru each post within than category to populate the column:

get_header(); ?>
    <div id="content">
        <div class="categories">
            $cats = get_categories();

            foreach ( $cats as $cat ) {
                $cat_id = $cat->term_id; ?>
                <div class="column" id="c0">
                    <h2><?php echo $cat->name; ?></h2>

                <?php query_posts( "cat=$cat_id&posts_per_page=100" );

                if ( have_posts() ) {
                    while ( have_posts() ) {


                </div> <!-- /column -->

                <?php } //post
            } ?> <!-- /foreach -->
        </div> <!-- /categories -->
    </div> <!-- /content -->

But within the custom post type I use this code and it generates and displays all the categories, but only displays 1 post per category.


if(have_posts()) { ?>

    <div id="content">
        <div class="categories">
            $args = array (
                'orderby'    => 'name',
                'order'      => 'ASC',
                'hide_empty' => true,
                //'number'    => '4'

            $terms = get_terms( 'bookmark_categories', $args );
            foreach ( $terms as $term ) { ?>

            <div class="column" id="c0">
                <div class="category">
                    <h2><?php echo $term->slug ?></h2>
                    <p class="count">
                        $items = get_posts( array (
                            'post_type'   => 'bookmarks',
                            'numberposts' => - 1,
                            'taxonomy'    => 'bookmark_categories',
                            'term'        => $term->name
                        ) );

                        $count = count( $items );
                        echo $count;


                $post_args = array (
                    'post_type'           => 'bookmarks',
                    'bookmark_categories' => $term->name
                $query     = new WP_Query( $post_args );

                while ( $query->have_posts() ) {
                    $url = get_post_meta($post->ID,'link_url',true); ?>

                <div class="link">

                        <a href="<?php echo $url; ?>" target="_blank" title="">
                            <?php the_post_thumbnail();?>


                <?php } // while

                wp_reset_postdata(); ?>
            </div> <!-- /column -->
            <?php } ?> <!-- /foreach -->
        </div> <!-- /categories -->
    </div> <!-- /content -->

<?php } else { // if posts
    get_template_part( 'content', 'none' );

  • Why are you using offset => 1?
    – sakibmoon
    Aug 17, 2014 at 10:54
  • Ah, that was redundant code from something else. I should have removed that line. I did now, but it has no effect on my current issue. Aug 17, 2014 at 11:00
  • I think you should be using $term->slug in the args rather than $term->name.
    – bonger
    Aug 17, 2014 at 16:31

1 Answer 1


Don't use query posts ever, my emphasis. It is just a bad function to use

Note: This function isn't meant to be used by plugins or themes. As explained later, there are better, more performant options to alter the main query. query_posts() is overly simplistic and problematic way to modify main query of a page by replacing it with new instance of the query. It is inefficient (re-runs SQL queries) and will outright fail in some circumstances (especially often when dealing with posts pagination).

Also, wp_reset_query should be used for query_posts. wp_reset_postdata is meant to be used for WP_Query and get_posts, which is the correct functions to use to create custom queries.

For additional info, check out this post I recently done.

get_posts uses the same parameters as WP_Query. Whenever you work with taxonomies and terms and in general with a tax_query, the default field that is used to retrieve the relevant info is term_id. slug is also valid and can also be used.

field (string) - Select taxonomy term by ('term_id'(default) or 'slug')

So change $term->name to either $term->term_id or $term->slug

  • Hope you got a notification to this answer. The notification system is a big stuff up this weekend. Aug 17, 2014 at 15:56
  • The whitespace can't be the problem, it's just ignored by php.
    – bonger
    Aug 17, 2014 at 16:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.