Support » Fixing WordPress » Creating an index of all posts sorted alphabetically by custom taxonomy

  • I am currently trying to put together an index of all posts sorted alphabetically by my custom taxonomy ‘rating’. My code has been applied to a custom page template with some success. Here is an abbreviated version of my code (since the content of all the columns isn’t particularly important here):

    <h1>Fantasy</h1>
      <table>
       <?php /////////////// Fantasy ///////////////
          $args = array( 'numberposts' => 100, 'order'=> 'ASC', 'orderby' => 'title', 'genre' => 'fantasy' );
          $myposts = get_posts( $args );
          foreach($myposts as $post) :
          setup_postdata($post);
          ?>
       <tr>
          <td><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></td>
          <td><?php if(get_post_meta($post->ID, 'Author', true)) {
             echo get_post_meta($post->ID, 'Author', true);
             } ?></td>
       </tr>
       <?php endforeach; wp_reset_postdata(); // END FANTASY // ?>
      </table>

    I have two issues with this:

    1. I have 20+ total genres. This means I have to copy-paste the code a lot, which makes for a clunky, messy template. I can’t think of a better way to do this, though, since some posts are assigned more than one category. If I called up all posts at once and added a ‘genre’ column, each title would only appear once with multiple genres listed beside it rather than multiple times, with a single genre listed each time. Is there a way to solve this that I haven’t thought of, or do I need to continue using my inelegant workaround?
    2. Right now I have sorted my table alphabetically by ‘title’, which works alright for the most part. My issue is that I would rather sort my list alphabetically by my custom taxonomy ‘rating’ (which doesn’t appear in the code above as I haven’t added it to my table yet, sorry!) and thereunder alphabetical by title. I can’t seem to find any examples of people doing something like this. Is it possible?

    Thank you for your help in advance!

Viewing 15 replies - 1 through 15 (of 32 total)
  • You can do what you want using filters to modify the query. There is sample code in this pastebin:
    http://pastebin.com/X5s2ha5e

    Thank you! Before I start experimenting with this, will this address both the repetition of code and the orderby issue or just one of the issues? And will this work in a page template?

    This addresses only issue #1. It will select Posts assigned at least one of the terms of the selected taxonomy and list the post under each term that it has been assigned. It does not address issue #2, but that could be solved by using additional terms in the filters.

    The code is only a sample to show how to do the query and structure the loop. You will need to adjust the output to suit your theme.

    The sample only shows the minimum output – A header for each term, and a single line for each post showing the term name and the Post title.

    I created a template with the following code:

    <?php /*
    Template Name: Post Index by Genre
    */ ?>
    
    <?php get_header(); ?>
    
        <?php
    
           // Use filters to sort a query on terms of a selected taxonomy.
           // See http://wordpress.mcdspot.com/2010/05/30/filters-to-modify-a-query/
           // for the code of the filters used.
    
           $taxonomy = 'genre';
           $mam_global_join = "JOIN $wpdb->term_relationships tr ON ($wpdb->posts.ID = tr.object_id)
          JOIN $wpdb->term_taxonomy tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id AND tt.taxonomy = '$taxonomy')
          JOIN $wpdb->terms t ON (tt.term_id = t.term_id)";
    
           $mam_global_fields = ", t.name AS term_name";
    
           $mam_global_orderby = "term_name ASC, $wpdb->posts.post_title ASC";
    
           $args = array(
              'ignore_sticky_posts' => 1,
              'post_type' => 'post',
           );
           $q = new WP_Query($args);
    
           $mam_global_join = $mam_global_fields = $mam_global_orderby = ''; // Turn off filters
           //print_r('<p>REQUEST:');print_r($q->request);print_r('</p>');
           //print_r('<p>POSTS:');print_r($q->posts);print_r('</p>');
    
           if ($q->have_posts()) {
              $current_term = '';
              while ($q->have_posts()) {
                 $q->the_post();
                 if ($current_term != $post->term_name) {
                    $current_term = $post->term_name;
                    echo "<h2>TERM: $current_term</h2>";
                 }
                 echo "<p>TERM:$post->term_name &nbsp; &nbsp;  $post->post_title</p>";
              }
           }
    
        ?>
    
    <?php get_footer(); ?>

    All I got was a list of the 10 most recent posts. It didn’t even display the genre at all. Could you tell me what I’m doing wrong?

    Did you add the filter functions referenced in the pastebin to your functions.php?

    That did it, thank you very much! This will save me so much time.

    Anyone know how to call up ALL posts using the above code? This isn’t working:

    $args = array(
    	  'numberposts' => -1,
              'ignore_sticky_posts' => 1,
              'post_type' => 'post',
           );
           $q = new WP_Query($args);

    Nor is:

    $args = array(
    	  'posts_per_page' => -1,
              'ignore_sticky_posts' => 1,
              'post_type' => 'post',
           );
           $q = new WP_Query($args);

    Strange, the second example works for me.

    When I use the second example, all I get is a blank page. When I use ‘posts_per_page’ => 50, it works. When I go as high as ‘posts_per_page’ => 100, I get a blank page again.

    I can’t go that high because I don’t have that many posts, but -1 retrieves all posts that meet have the taxonomy.

    Uncomment the line that dumps the request and post the output here. This line:

    //print_r('<p>REQUEST:');print_r($q->request);print_r('</p>');

    I uncommented and tried again using -1. I still only get a blank page.

    There must be a syntax error in the code. Otherwise, you would get the output of the print_r line.

    When I change the -1 back to 50, the pring line gives me:
    REQUEST:SELECT SQL_CALC_FOUND_ROWS wp_posts.*, t.name AS term_name FROM wp_posts JOIN wp_term_relationships tr ON (wp_posts.ID = tr.object_id) JOIN wp_term_taxonomy tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id AND tt.taxonomy = 'genre') JOIN wp_terms t ON (tt.term_id = t.term_id) WHERE 1=1 AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private') ORDER BY term_name ASC, wp_posts.post_title ASC LIMIT 0, 50

    I don’t know if that’s helpful.

    All the -1 should do is elimiate the ‘LIMIT 0,50’ from the request. It should not cause a blank page.

    Please copy and paste the code with the -1 here so the exact code can be seen.

    <?php /*
    Template Name: Post Index by Genre
    */ ?>
    
    <?php get_header(); ?>
    
        <?php
    
           // Use filters to sort a query on terms of a selected taxonomy.
           // See http://wordpress.mcdspot.com/2010/05/30/filters-to-modify-a-query/
           // for the code of the filters used.
    
           $taxonomy = 'genre';
           $mam_global_join = "JOIN $wpdb->term_relationships tr ON ($wpdb->posts.ID = tr.object_id)
          JOIN $wpdb->term_taxonomy tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id AND tt.taxonomy = '$taxonomy')
          JOIN $wpdb->terms t ON (tt.term_id = t.term_id)";
    
           $mam_global_fields = ", t.name AS term_name";
    
           $mam_global_orderby = "term_name ASC, $wpdb->posts.post_title ASC";
    
    $args = array(
    		  'posts_per_page' => -1,
              'ignore_sticky_posts' => 1,
              'post_type' => 'post',
           );
           $q = new WP_Query($args);
    
           $mam_global_join = $mam_global_fields = $mam_global_orderby = ''; // Turn off filters
           print_r('<p>REQUEST:');print_r($q->request);print_r('</p>');
           //print_r('<p>POSTS:');print_r($q->posts);print_r('</p>');
    
           if ($q->have_posts()) {
              $current_term = '';
              while ($q->have_posts()) {
                 $q->the_post();
                 if ($current_term != $post->term_name) {
                    $current_term = $post->term_name;
                    echo "<h2>TERM: $current_term</h2>";
                 }
                 echo "<p>TERM:$post->term_name &nbsp; &nbsp;  $post->post_title</p>";
              }
           }
    
        ?>
    
    <?php get_footer(); ?>
Viewing 15 replies - 1 through 15 (of 32 total)
  • The topic ‘Creating an index of all posts sorted alphabetically by custom taxonomy’ is closed to new replies.