3

I am using wp_get_archive() in category.php.

If I am on page of category=2 it should show my archives of only that category. However it is for all the categories. Following is the code for my category.php as well as archive.php

<?php get_header(); ?>
 <?php 
   $args =array(               
                'posts_per_page' =>1,                 
           );
  $loop = new WP_Query( $args );                                            
  if($loop->have_posts()):while ( $loop->have_posts() ): $loop->the_post();
   the_content();
  endwhile;
  endif;
 ?>
 <?php wp_get_archives( array( 'type' => 'daily') ); ?>

First part that is to show archive of specific category was solved by this code thanks to Pieter Goosen - answer given by him on How do I change the sql query for wp_get_archive()

But now problem is that if i go to that archive from the category page, i need to also show only posts from that category only.

6
  • @Pieter Goosen second part to the question please help Commented Jan 30, 2015 at 8:37
  • First, you should really make the changes to your category and archive pages as I have suggested in the previous question. As your code stands, it will display the same post for all archives. Also, your custom query, not being reset, might influence other queries Commented Jan 30, 2015 at 8:42
  • You mean to say that i should use wp_reset_query() after endif. And i need to use that second code to restrict the no of posts to 1 , right. Commented Jan 30, 2015 at 9:16
  • No, please see my edit to the previous post. Your custom query stuffs up your whole setup. As I stated in the previous question, use pre_get_posts. Remove the custom query and use the default loop Commented Jan 30, 2015 at 9:37
  • yup i did wat u asked me to do Commented Jan 30, 2015 at 9:46

2 Answers 2

3

Before I start again, I just want to reinforce the fact you should not run a custom query in place of the main query on your archive pages. Please see this post to learn when you should use a custom query and where not. I you do not switch back to the default loop, then my solution will not work

In the previous post we have already solved the issue to only show the archives from the currently viewed category. The next issue is to only show posts from the current category when you visit the date archive from the current category

To accomplish this, we are going to make use of the following filters and actions

In order for the date archive page to know if the request came from a category page and to serve up the posts from only that category, we need to set some kind of referrer. As wp_get_referer() and $_SERVER['HTTP_REFERER'] is very unreliable (see this post for more info), we are going to use extra parameters in the URL to set values which we will check and use to determine which posts to serve up. To achieve this, we will set a new query variable cq which will hold the current category ID.

Next we need to modify the archive links from wp_get_archives() when they are displayed on category pages. We need to add the category ID to the URL so that we can read the category ID when we are on the archive page to alter the main query. To alter the links to include our custom query variable, we will make use of the get_archives_link filter to alter the links and add_query_arg to add the custom query variables to the new links

Now that we have the new links, if we click on the links from the category pages, you will see something like this added to your URL on the date archive pages ?cq=21. 21 is the category ID in my test site.

We must now check whenever we are on a date archive page if the new quey variable is appended to the URL. We will use filter_input( INPUT_GET, 'cq', FILTER_VALIDATE_INT ); to get the value, sanitize and validate the value from the URL. If the new query variable is appended to the URL, we need to adjust our main query to only return posts from the category which ID is added as a value to cq. pre_get_posts will be used here

Here is the complete code:

add_filter( 'query_vars', function ( $vars ) {

    $query_vars = [
        'cq'  
    ];
    $vars = array_merge( $vars, $query_vars );

    return $vars;

});


add_filter( 'get_archives_link', function ( $link_html ) {

    if( is_category() ) {

        preg_match ( "/href='(.+?)'/", $link_html, $url );

        $old_url = $url[1];
        $new_url = add_query_arg( ['cq' => get_queried_object_id()], $old_url );
        $link_html = str_replace( $old_url, $new_url, $link_html );

    }

    return $link_html;

});

add_action( 'pre_get_posts', function ( $q ) {

    $cat_id = filter_input( INPUT_GET, 'cq', FILTER_VALIDATE_INT );
    if(     !is_admin() // Target only the front end
         && $q->is_main_query() // Target only the main query
         && $q->is_date() // Only target the date archive pages
         && $cat_id // Only run the condition if we have a valid ID
    ) {

        $q->set( 'cat', $cat_id );

    }
});
4
  • code worked like charm. Meanwhile i was looking for solution.Actually i am using archive-calender widget plugin and thought that changing the sql queries of wp_get_archive will also change the functionality of that widget.But that was not the case. Then i looked for the appended &cat=get_queried_object_id() to daily_archive_link in the files of the plugin. It worked.My purpose was solved.Thanks a lot . But i saw a problem that when i am on date archive page, then archives listed in sidebar are not according to category.. Commented Jan 31, 2015 at 7:43
  • Yes, that widget has to reworked as well. You should be able to accomplish that with about the same setup as this answer. If you don't come right, post a new question. I'm off for today as this is my wedding anniversary. Treating the wife a bit. While have a look at this on Monday. Enjoy :-) Commented Jan 31, 2015 at 7:48
  • congrats and enjoy and have a lot of fun The widget is also working awesome thanks to you Commented Jan 31, 2015 at 8:03
  • Thanks, we had blast :-) Great you got the widget working. Enjoy :-) Commented Feb 1, 2015 at 7:30
0

Complementing @Pieter Goosen incredible solution I had to add a WHERE and JOIN clausules to the get_archives function for the filter bring only the period relative to the posts associated with the category:

/* Add category WHERE parameter to the get_archives function */
function categories_archive_where($sql_where, $parsed_args){
    global $wpdb;
    $cat_id = get_query_var('cq') ?: (is_category() ? get_queried_object_id() : false);
    if($cat_id){
         $sql_where = $wpdb->prepare("WHERE post_type = %s AND post_status = 'publish' AND {$wpdb->term_relationships}.term_taxonomy_id = %s", $parsed_args['post_type'], $cat_id);
    }
    return $sql_where;
}
add_filter('getarchives_where', 'categories_archive_where', 99, 2);

/* Add category JOIN parameter to the get_archives function */
function categories_archive_join($sql_join){
    global $wpdb;
    $cat_id = get_query_var('cq') ?: (is_category() ? get_queried_object_id() : false);
    if($cat_id){
         $sql_join = "JOIN {$wpdb->term_relationships} ON {$wpdb->posts}.ID = {$wpdb->term_relationships}.object_id";
    }
    return $sql_join;
}
add_filter('getarchives_join', 'categories_archive_join', 99, 1);

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.