I'm trying to get a piece of code I can use sitewide to print lists of posts (like people commonly do on their homepage to show their categories' most recent). With help from others over past years, I've gotten a certain distance, but not all the way, which is what I'm trying now.

You can see this piece goes in "functions.php" I can make it get categories OR tags, offset them. I would like to add to this though. I would like to be able to select a category OR tag, but then exclude posts that also have another tag/cat. For example, I want to print a list of "grizzly-bear" tag posts, but exclude any posts tagged "alaska" as well as (if possible) any post from the "blog" category. I'd also prefer if the function was changed so that I could enter the number of posts the same way I do the offset (because the way it is now, I have to make a new function for each number of posts I want).

Right now I print it with:

<?php my_custom_loop(NULL, 'blogs', 0); ?>

Can anyone assist with how to add that stuff? Particularly with changing this code so that the number of posts, kind of so it'd be printable with something like:

<?php my_custom_loop(NULL, 'blogs', 0, numberofposts, excludecategoryorNULLL, excludetagorNULL); ?>

Function as it is now:

// Universal category - tag - offset code function
function my_custom_loop($category, $tag, $offset) {
          // showposts has been replaced, use 'posts_per_page' instead
          // 'showposts'        =>10,
          'posts_per_page'      => 10,
          // this has been replaced, use 'ignore_sticky_posts'
          // 'caller_get_posts' => 1,
          'ignore_sticky_posts' => true,

        if ($category) {
          $args['cat'] = $category;

        if ($tag) {
          $args['tag'] = $tag;

        if ($offset) {
          $args['offset'] = $offset;

        $my_query = new WP_Query($args);
        // ... rest of function to output loop 

if( $my_query->have_posts() ) {
            while ($my_query->have_posts()) : $my_query->the_post(); ?>
              <a href="<?php the_permalink() ?>" >
                <?php the_title(); ?>
        } //if ($my_query)

        wp_reset_query();  // Restore global post data stomped by the_post().   

1 Answer 1


I wonder if you mean this kind of a loop wrapper:

        $args   = [ 'post_type' => 'page', 'posts_per_page' => 2 ],
        $before = 'template-parts/wpse-before',
        $loop   = 'template-parts/wpse-loop',
        $after  = 'template-parts/wpse-after'

where we define it in the functions.php file, in the current theme directory:

 * Simple loop wrapper

function wpse_257857_loop( $args, $before, $loop, $after ) 
    $defaults = [
        'posts_per_page'      => 10,
        'ignore_sticky_posts' => true,

    $args = wp_parse_args( $args, $defaults );

    $query = new WP_Query( $args );

    if( $query->have_posts() )
        get_template_part( $before );
        while( $query->have_posts() )
            get_template_part( $loop );
        get_template_part( $after );


Note that we don't need wp_reset_query(), instead we use wp_reset_postdata().

We have to define the template parts, in the current theme directory, that we load with get_template_part().

Here's an example:

  • /template-parts/wpse-before.php contains:

    <div class="wpse-loop">
  • /template-parts/wpse-after.php contains:

  • /template-parts/wpse-loop.php contains:

        <a href="<?php the_permalink() ?>" >
            <?php the_title(); ?>

Hope you can adjust it to your needs!

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.