WordPress.org

Support

Support » How-To and Troubleshooting » [Resolved] Prioritizing posts by category in a date-sorted loop

[Resolved] Prioritizing posts by category in a date-sorted loop

  • Hi. To start it off, my loop is sorted by dates. The posts are grouped and the dates appear once on top of posts of the same date like this:

    –Date–
    Post1
    Post2
    Post3

    –Date before that–
    Post 4
    Post 5

    etc

    I’m trying to achieve a result, where if a post belongs to a certain predetermined category, it would be moved above others under a date as such:

    –Date–
    Post3 (special category)
    Post1
    Post2

    –Date before that–
    etc

    I can’t think of anything. Is achieving such a result even possible with php and WordPress codex? I would be glad if anyone could point me towards helpful materials or some code, because I lack the general idea of how to execute this concept.

    My loop: http://pastebin.com/Pp0rA5j7
    Sample site: http://goldenred.web44.net (I would like to move the post test 6 with the category “test” above others under February 3, 2013)

    I would be really thankful if anyone could help.

Viewing 15 replies - 1 through 15 (of 39 total)
  • Did some additional research on the topic and found something that seemed somewhat relevant to the topic. I’m not sure though.

    http://codex.wordpress.org/Function_Reference/query_posts
    http://codex.wordpress.org/Plugin_API/Action_Reference/pre_get_posts

    Would it be possible to add “parent” status to the date labels and use conditional tags on everything before the next parent or something similar?

    I’m thinking a request like this would definitely have something to do with the query parameters, multiple loops or functions. Maybe creating the posts with one loop and sorting in another or something of that nature. I’ll keep on looking for the answer and I would really appreciate if someone took the time to comment on this endeavor.

    It’s quite difficult in the sense that there’s not much information on a such a layout, but I’ll try and manage. If anyone knows of a GPL theme that uses categorizing like that I would appreciate if you could mention it.

    I would be extremely thankful for anything that could help me. I’m prepared that this could take me a very long while.

    Alright I’m starting to think this could be done with queries. http://codex.wordpress.org/Displaying_Posts_Using_a_Custom_Select_Query

    I found a plugin (http://wordpress.org/extend/plugins/my-posts-order/) that claims to do almost what I need, but I’m not really sure how to implement it with my date sorting. I think it also uses the query functions and I generally prefer to have the least amount of plugins possible, but I’ll go with it if necessary and it’s possible to implement it. At least I’m starting to get some idea of what needs to be done.

    Any comments would be greatly appreciated.

    Alright, since I posted this thread I’ve managed to obtain this code, which is unfortunately broken (posts don’t show):

    <?php
    $w_h = $w_d = $last = 0;
    // init variables to concatenate content later
    $primary_posts = $secondary_posts = '';
    // empty array to fill later
    $category_names = array();
    if (have_posts()) :
        while (have_posts()) :
            the_post();
            if ( date('Yz') == get_the_time('Yz') ) {
                if (!$w_d++) echo '<h6>Today</h6>';
            } elseif ( date('Yz')-1 == get_the_time('Yz') ) {
                if (!$w_h++) echo '<h6>Yesterday</h6>';
            } else {
                echo the_date('', '<h3>', '</h3>');
            };
            // get post categories
            $category_objects = get_the_category();
            foreach($category_objects as $category_object) {
                $category_names[] = $category_object->name;
            }
            // if posts belongs to category 'test'
            if( in_array('test', $category_names) ) {
                $primary_posts .= '<div class="post">Post of category "test"';
                // title, categories and excerpt goes here
                $primary_posts .= '</div><!-- .post -->';
            }
            else {
                $secondary_posts .= '<div class="post">Post of category other than "test"';
                 // title, categories and excerpt goes here
                $secondary_posts .= '</div><!-- .post -->';
           }
    
        endwhile;
        // output all posts of category "test"
        echo $primary_posts;
        // output all posts of category other than "test"
        echo $secondary_posts;
    endif; ?>

    The author of the code thought it was a bad idea in the end, but maybe that’s enough to help someone think towards the right direction. The general idea was to collect 2 variables, posts under the category test and all others, and print the posts marked with test before the others within the group. I can’t comment much on it otherwise, other than it may be an important step towards what’s needed.

    I’ve also received suggestions to use custom meta fields for high priority posts (‘test’ directory) and WP_Query to achieve the desired result.

    This is merely a quest I’m after for myself. This isn’t a job for a client or anything. I would be extremely glad if anyone could help, because this feature would be a core function to my website.

    If you don’t have any ideas about the code, could you please comment on the possibility of this idea, because if I fail to receive help from here, I might hire a freelancer to do the job. I wouldn’t want to get ripped off if this turns out to be an insanely difficult request. What makes me cautious is that this one of the very few times where I haven’t actually received any help or tips after quite a bit of research.

    I’m also willing to switch the base mechanism of how the posts are sorted into groups towards a possibly more flexible option. I found something like this (using WP_Query): http://pastebin.com/McM8iwB3. Maybe then it would be easier to implement the prioritizing system within the group? Out of the box solutions have often proved to be the key to my hardest problems.

    I’m looking forward to your responses.

    Best regards,
    ggg377

    Moderator keesiemeijer

    @keesiemeijer

    Do you want pagination for this page?

    Thanks for your reply, keesiemeijer!

    As for pagination, it doesn’t really matter as long as the needed functionality is there. Hopefully I’ll be able to implement infinite scrolling on it sometime in the future, but that’s a different topic.

    Moderator keesiemeijer

    @keesiemeijer

    Without pagination, you don’t have the problem with a post from the same date (and maybe in the special category) on the next page. With pagination it makes it very complicated. You could do a (very expensive) query for all posts and reorder them how you want with the “post__in” parameter. But if you have a lot of posts (lets say over 1000) this will become a very large query (on the database) on pages where you need this functionality. I’ve never used infinite scrolling so I don’t know if it uses the pagination from WordPress (logically I think it does).
    If someone knows, please chime in.

    I’m sorry but I don’t really have time to look into this right now.

    I can assure you the blog will be dealing with a big number of posts (that’s why I’m using grouping like that in the first place). Would going with no pagination mean hundreds or even thousands of posts being displayed at once on the home page? I think if that was the case, I’d be better off without the needed functionality and pagination.

    Another thing is, I personally don’t see a problem if a post from the same date group appears on the next page, as that happens now as well, however if the issue is with the script “not reaching” the posts that appear on next pages then that’s definitely understandable. Which I guess would leave me with 2 pretty bad choices – no pagination, or a cumbersome query. However if that’s only a navigation/cosmetic issue then that wouldn’t be a problem. Oh well. I’m open for more ideas.

    By the way infinite scrolling does use pagination, you usually place the selectors around the pagination functions in your theme.

    Anyway, thanks a lot for contributing. Hopefully one day 🙂

    Moderator keesiemeijer

    @keesiemeijer

    Here is an example to give you an Idea how you could do this with multiple loops. The first loop gets all the id’s of the current page and sorts them by day with the specific category moved to the top. The second loop re-uses these id’s for the display of the posts in the right order. This lets you also have pagination if you want:

    <?php 
    
    	$date_ids = array();
    
    	// normal loop to get all post IDs by date and category
    	while ( have_posts() ) { the_post(); 
    
    		$post_date = date('Ynj', strtotime( $post->post_date ));
    
    		// change the category ID
    		if(in_category(1)) {
    			$date_ids[$post_date]['first'][] = $post->ID;
    		} else {
    			$date_ids[$post_date]['last'][] = $post->ID;
    		}
    
    	} // end of normal loop
    
    	// sort all IDs
    	$all_ids = array();
    
    	foreach($date_ids as $key => $date){
    
    		if(isset($date['first'])) {
    			$all_ids = array_merge($all_ids, $date['first'] );
    		}
    		if(isset($date['last'])){
    			$all_ids = array_merge($all_ids, $date['last'] );
    		}
    	}	
    
    ?>
    
    <!-- put pagination functions before the display loop here -->
    
    <?php
    
    	// use a custom loop to show the posts in the correct order
    	// this way we don't mess with the pagination
    
    	$args =  array(
    	  'post__in' => $all_ids,
    	  'orderby' => 'post__in',
    	  'ignore_sticky_posts' => 1
    	);
    
    	$the_query = new WP_Query( $args ); ?>
    
    <!-- the loop to display the posts -->
    <?php while ( $the_query->have_posts() ) : $the_query->the_post(); ?>
    
    	<!-- put your loop code here -->
    	<?php the_title(); ?>
    
    <?php endwhile; ?>
    <?php wp_reset_postdata(); ?>
    
    <!-- put pagination functions after the display loop here -->

    Change the category ID in if(in_category(1)) to the category you want on top of the days posts.

    I couldn’t thank you enough keesiemeijer. Your concept as well as the code work as needed.

    However, I have encountered two minor bugs as well. The dates “Today” and “Yesterday” receive the date label for each post for some reason, even though the code is still the same. In the case of “the_date”, it works exactly as intended. This is the relevant code:

    <?php $w_h = $w_d = $last = 0; ?>
    
                    <div class="indexdate"><?php
        if ( date('Yz') == get_the_time('Yz') ) {
            if (!$w_d++) echo '<h6>Today</h6>';
        } elseif ( date('Yz')-1 == get_the_time('Yz') ) {
            if (!$w_h++) echo '<h6>Yesterday</h6>';
        } else {
            echo the_date('', '<h3>', '</h3>');
        };
    ?>

    Also this code gets implemented for every post now, even though it’s intended only for the first posts of groups.

    <div id="post" <?php if( get_the_time('Yz') != $last ) { $last = get_the_time('Yz'); echo ' class="first" '; } ?>>

    I think it conflicts with an earlier code, but I’m not sure.

    index.html: http://pastebin.com/7aeA8qrU
    Sample of the code in action and the bug: http://goldenred.web44.net

    Ugh, I noticed another problem. Sometimes, posts marked with “test” appear on the second page even when the date label is on the first page and there are no other posts marked as “test” under that date label. The post marked with “test” is moved to the top of the second page instead of being moved on the first page to the top of the list.

    Actually that’s another issue that I need to take care of soon. I don’t want the date labels to appear twice under any circumstances (even if posts for a particular date appear through many pages). I suppose if it would be possible to remove duplicate displays of date labels on multiple pages, that problem would be automatically taken care of (and that would also save me from looking into that in the future).

    Of course if it’s possible to take care of that in another manner then I would be happy to try that, because achieving the objectives of this thread is the highest priority. The previous paragraph was just something that I thought would be useful to mention.

    I’m looking forward to all replies and I hope I’m not causing too much trouble. Once again, thank you for your effort keesiemeijer, you’ve already done enough truthfully.

    Moderator keesiemeijer

    @keesiemeijer

    What do you want to do? Have one header for the “today” and “yesterday” posts, or have the header on all “today” and “yesterday” posts? Should all “today” and “yesterday” posts get a “first” class?

    “Today” and “yesterday” posts should only receive one header per group (per one date). So if there’s 3 posts from 02/03/2013 for example, these should only receive one header.

    Only the topmost posts from the “today”, “yesterday” and “the_date” groups should receive “first” class so that it would be possible to remove the top border.

    Moderator keesiemeijer

    @keesiemeijer

    Another thing you could do is loop through dates instead of through posts. This way all date posts are on the same page. Here is an example: http://pastebin.com/KhSvg1uz
    Change the category ID in if(in_category(1)) to the category you want on top of the same date posts.

    To see the pagination work go to /page/2. Unfortunatly I don’t have any more time to work on this today.

    That is an impressive idea as well as coding. I am really thankful you’re willing to put in effort to help me. The last bit of code you posted solved all pagination issues.

    The only problems left are the date labels being shown on all posts in “Today” and “Yesterday” (seeing how it works for “the_date” it can’t be that bad) and getting different styling for top posts within dates to work. I’ll get to solving these problems now. I’ll report if it proves to be too difficult. Once again, thank you.

    Edit: found another issue. Only a maximum of 5 posts get shown per date (the “test” posts if there are any and the newest posts of other categories), an example is February 3, I have another post on that date, which isn’t shown. Other posts are hidden.

    Unfortunately I think I won’t be able to figure that out. Hopefully it’s possible to get that resolved, because overall, the code is exactly what I need.

Viewing 15 replies - 1 through 15 (of 39 total)
  • The topic ‘[Resolved] Prioritizing posts by category in a date-sorted loop’ is closed to new replies.
Skip to toolbar