• rrajakumar

    (@rrajakumar)


    I’ve seen a few people looking for a solution to the problem of sorting posts by both month and category, and I had a similar need. I wanted our blog set up so that when you are looking at a single category, the monthly archive section in the sidebar would be filtered for that category alone, and return a page of results for that month and category. I have pretty much got it working and thought I’d share what I did:

    First, you need to create a new ‘type’ for wp_get_archives, which has a variable $mcat that gets the value of whatever category you are currently looking at. To do that, you need to edit /wp_includes/template_functions_general.php:

    Replace the existing wp_get_archives function with:
    function wp_get_archives($args = '') {
    parse_str($args, $r);
    if ( !isset($r['type']) )
    $r['type'] = '';
    if ( !isset($r['limit']) )
    $r['limit'] = '';
    if ( !isset($r['format']) )
    $r['format'] = 'html';
    if ( !isset($r['before']) )
    $r['before'] = '';
    if ( !isset($r['after']) )
    $r['after'] = '';
    if ( !isset($r['show_post_count']) )
    $r['show_post_count'] = false;
    if ( !isset($r['mcat']) )
    $r['mcat'] = false;

    get_archives($r['type'], $r['limit'], $r['format'], $r['before'], $r['after'], $r['show_post_count'], $r['mcat']);
    }

    AND insert the following elseif into the list of types in the get_archives function:

    elseif ( 'catmonthly' == $type ) {
    $arcresults = $wpdb->get_results("SELECT DISTINCT YEAR(post_date) AS
    year, MONTH(post_date) AS month, count(ID) as posts FROM $wpdb->posts, $wpdb->post2cat WHERE post_date < '$now' AND category_id = $mcat AND post_date != '0000-00-00 00:00:00' AND post_status = 'publish' GROUP BY YEAR(post_date), MONTH(post_date) ORDER BY post_date DESC" . $limit);
    if ( $arcresults ) {
    $afterafter = $after;
    foreach ( $arcresults as $arcresult ) {
    $url = get_month_link($arcresult->year, $arcresult->month) ."&cat=" .$mcat;
    if ( $show_post_count ) {
    $text = sprintf('%s %d', $month[zeroise($arcresult->month,2)], $arcresult->year);
    $after = '&nbsp;('.$arcresult->posts.')' . $afterafter;
    } else {
    $text = sprintf('%s %d', $month[zeroise($arcresult->month,2)], $arcresult->year);
    }
    echo get_archives_link($url, $text, $format, $before, $after);
    }
    }
    }

    The important parts are the database query, which incorporates the new criterion, and the value that is assigned to $url, which now adds the category filter to the URL of the results page.

    Next, you need to modify sidebar.php:

    Replace:

    <li><h2>Archives</h2>
    <ul>
    <?php wp_get_archives('type=monthly'); ?>
    </ul>
    </li>

    with:

    <?php /* Whether this is a category archive */ if (is_category()) { ?>

    <li><h2>Archives for <?php single_cat_title(''); ?></h2>
    <ul>
    <?php $catmnthquery=("type=catmonthly&mcat=" .$cat); wp_get_archives($catmnthquery); ?>
    </ul>
    </li>
    <?php } else { ?>

    <li><h2>Archives</h2>
    <ul>
    <?php wp_get_archives('type=monthly'); ?>
    </ul>
    </li>
    <?php } ?>

    Now, if you are browsing a category, the ‘Archives’ heading in the sidebar includes the name of the category, the results (months) listed should be for that category only, and the links should return posts filtered by both criteria.

    I’m new to PHP/MySQL, so I’m sure there’s a cleaner way to do all that, but I thought it might be useful.

Viewing 16 replies (of 16 total)
  • OK. For 2.1:

    a) don’t replace wp_get_archives with the function above. That won’t work. Just add

    ,'mcat' => false after the currently last element in the “defaults” array.

    Then add the “elseif code from above, but modify the SQL statement – this is the query that works.

    $arcresults = $wpdb->get_results("SELECT DISTINCT YEAR(post_date) ASyear, MONTH(post_date) ASmonth, count(ID) as posts FROM $wpdb->posts, $wpdb->post2cat WHERE $wpdb->posts.ID = $wpdb->post2cat.post_id AND $wpdb->post2cat.category_id = '$mcat' AND $wpdb->posts.post_type = 'post' AND $wpdb->posts.post_status = 'publish' GROUP BY YEAR(post_date), MONTH(post_date) ORDER BY post_date DESC".$limit);

    The template command as above.

    Remember to note the changes you made because you’ll have to adjust the core file after each update.

Viewing 16 replies (of 16 total)
  • The topic ‘Archives by Date and Category’ is closed to new replies.