6

I edited my loop in archives.php in order to work with pagination and with the Category Post List Widget. I basically pieced it all together from random code and ideas and am now so far from the default post query that I'm having trouble getting back to square one. The reason I need to get back to square one is that I need two things:

1) My code is messing up my category posts when the post has two category tags. When that happens, they get placed in the wrong categories (or don't get placed at all).

2) By doing this custom coding, I lost the query for 'tags' as well so the tag pages don't work correctly.

I need to get back to square one so I can set up tags and category posts to be displayed correctly but within the correct <li>s that I style. I'm not sure if I even need the Category Post List widget anymore because, if I'm not mistaken, I can call the set_post_thumbnail_size();, the_title();, the_excerpt(), etc. without the widget and just style my own list items.

Anyhow, here's the code I've got, I imagine I need to scrub a bunch of it to get back where I need to go. Thank you so much for the help, I really appreciate it.

<?php if (have_posts()) : ?>

<ul style="list-style-type:none;">

<?php
if ($paged == 0)
  $offset = 0;
else
  $offset = ($paged - 1) * 11;
global $post;
$category = get_the_category($post->ID);
$category = $category[0]->cat_ID;
$myposts = get_posts(array('numberposts' => 11, 'offset' => $offset, 'category__in' => array($category), 'post__not_in' => array($post->ID),'post_status'=>'publish'));
foreach($myposts as $post) :
setup_postdata($post);
?>


<li id="category_li">
    <div id="image_con">
        <div id="image_recent">
        <a href="<?php the_permalink(); ?>"><?php set_post_thumbnail_size( 200, 200 );
the_post_thumbnail(); ?></a>
        </div>
    </div>

    <div id="cr_content">
    <a href="<?php the_permalink(); ?>">
    <div class="gloss_glam_font"> <?php the_title(); ?></div>
    <hr>
    <div class="excerpt_cat"><?php the_excerpt(); ?></div>
    </a>
    </div>

    <div id="clearfix">
    </div>
</li>

<?php endforeach; ?>
<?php wp_reset_query(); ?>
</ul>


<?php while (have_posts()) : the_post(); ?>

<?php endwhile; ?>

<?php if (function_exists("pagination")) {
    pagination($additional_loop->max_num_pages);
} ?>
    <?php else :

        if ( is_category() ) { // If this is a category archive
        printf("<div class='post-content'><p><em><strong>Not Found:</strong> Sorry, but there aren't any posts in the &middot;<strong>%s</strong>&middot; category yet.</em></p></div>", single_cat_title('',false));
    } else if ( is_date() ) { // If this is a date archive
        echo("<div class='post-content'><p><em><strong>Not Found:</strong> Sorry, but there aren't any posts with this date.</em></p></div>");
    } else if ( is_author() ) { // If this is a category archive
        $userdata = get_userdatabylogin(get_query_var('author_name'));
        printf("<div class='post-content'><p><em><strong>Not Found:</strong> Sorry, but there aren't any posts by &middot;<strong>%s</strong>&middot; yet.</em></p></div>", $userdata->display_name);
    } else {
        echo("<div class='post-content'><p><em>No posts found.</em></p></div>");
    }

endif; ?>

EDIT

Alright, I edited it and I can't figure out where I'm off. I'm using my tag.php template as an example here (not the category.php). Here's what I've done so far (based off the code provided by Chip in the answers):

function wpse63424_filter_pre_get_posts( $query ) {
    if ( ! is_main_query() ) {
        return $query;
    } else {
        if ( is_category() || is_tag() ) {
            $query->set( 'posts_per_page',11 );
        }
        return $query;
    }
}
add_filter( 'pre_get_posts', 'wpse63424_filter_pre_get_posts' );

$tag = get_query_var('tag');
$myposts = get_posts('tag__in' => array($tag));
foreach($myposts as $post) :
setup_postdata($post);

My thinking was that I've set a filter of 11 posts per page, I query for a specific tag, set the posts to the tag in that array and then set up the posts accordingly. When I just run get_posts(); it returns 11 posts per page unfiltered so I know that Chip's code works fine. I guess I'm not understanding how the functions are called correctly yet...

2 Answers 2

9

First, for layout and CSS styling, I would recommend creating template files for the contexts you want to customize; i.e. create a category.php and a tag.php for the category and tag index archive pages, respectively. In either case, copy archive.php (or, if it doesn't exist, copy index.php), and rename the copy as category.php. Then, modify the markup as necessary.

For CSS, ensure that you're using body_class() in your Theme, and then you can use the *category and tag-based CSS classes applied to the <body> tag.

The next step is customizing the query to output 10 posts per page, instead of 10, for category/tag archive index pages. For that, use the pre_get_posts filter. Add the following callback and add_filter() call to functions.php:

function wpse63424_filter_pre_get_posts( $query ) {
    if ( ! is_main_query() ) {
        return $query;
    } else {
        if ( is_category() || is_tag() ) {
            $query->set( 'posts_per_page',11 );
        }
        return $query;
    }
}
add_filter( 'pre_get_posts', 'wpse63424_filter_pre_get_posts' );

This callback tells WordPress:

  1. If the query isn't the main query, then return it without modifying it. (This prevents, e.g., Recent Posts widget query, or navigation menus from being impacted.)
  2. If the current page is either a category archive index or a tag archive index, change the 'posts_per_page' query variable to 11, then return the query.
9
  • Oh wow, great. I have a question before I move forward. With this code, it seems that I wouldn't need to make both a 'category' and a 'tag' template since the conditional has "||" (determining between category and tag there). The CSS styling would be the same for both categories and tags so would you still recommend making two different templates? Commented Aug 29, 2012 at 13:46
  • 1
    The loop query modification won't change the actual HTML markup. So, if you need to modify HTML markup, you'll need to make those changes directly in the template. Thus the need for both a category.php and a tag.php. (Or, if you're using a loop.php template-part file, create loop-tag.php and loop-category.php, etc.) Commented Aug 29, 2012 at 13:52
  • just another comment: to (re-)build a category archive, don't use $category = get_the_category($post->ID); but use $category = get_query_var('cat'); - get_the_category() gets categories of a post which can be random in the category archive if posts have more than one category
    – Michael
    Commented Aug 29, 2012 at 15:40
  • 1
    The callback and add_action() call belong in functions.php, not in the template file. Commented Aug 29, 2012 at 17:15
  • 1
    Also: you need to get rid of all of your custom loop code. Just use the default loop code for your Theme. Use whatever is in index.php, or loop.php, or whatever your Theme uses. You don't need to modify the default loop markup in any way whatsoever. Commented Aug 29, 2012 at 17:20
1

I don't know if something's changed with the latest version of WP (4.4+), but is_main_query() will return a false positive as-is. It should be:

function wpse63424_filter_pre_get_posts( $query ) {
    if ( ! $query->is_main_query() ) {
        return $query;
    } else {
        if ( is_category() || is_tag() ) {
            $query->set( 'posts_per_page',11 );
        }
        return $query;
    }
}
add_filter( 'pre_get_posts', 'wpse63424_filter_pre_get_posts' );

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.