php - Grouping WordPress custom posts by taxonomy -


i've got custom post type called "products", has 2 custom taxonomies - "product-range" , "product-categories". range serves top-level grouping, whereas category sub-grouping within that.

i've set-up taxonomy-product-range.php template features following code:

<?php $terms = get_terms('product-categories'); foreach( $terms $term ): ?>       <h2><?php echo $term->name;?></h2> <ul>      <?php                              $posts = get_posts(array(         'post_type' => 'products',         'taxonomy' => $term->taxonomy,         'term' => $term->slug,         'nopaging' => true     ));     foreach($posts $post): setup_postdata($post);     ?>      <li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>      <?php endforeach; ?>  </ul>             <?php endforeach; ?> 

this works expected outputting products , grouping them product category. however, outputs of products, regardless of archive you're viewing. need output posts archive you're viewing.

this feels it's there, i'm not sure how fix it.

== edit ==

each of products belong 1 "range" , 1 "category". when people visit product-range archive page, i'm trying display following:

<h1>range title</h1> <h2>category 1 title</h2> <ul> <li>product 1 title</li> <li>product 2 title</li> <li>product 3 title</li> </ul> <h2>category 2 title</h2> <ul> <li>product 4 title</li> <li>product 5 title</li> <li>product 6 title</li> </ul> 

simple remove code have , replace default loop. should not replace main query custom one. use pre_get_posts alter main query according needs.

this taxonomy page should

if ( have_posts() ) {     while ( have_posts() ) {     the_post();          // template tags , markup      } } 

as problem sorting, tackle using usort , thee the_posts filter sorting before loop runs after main query has run. not use multiple loops quite expensive , resource intensive, , breaks page functionalities

i have commented code can easy follow , understand. (note: following code untested , requires php 5.4+ due array dereferencing)

add_filter( 'the_posts', function ( $posts, $q )  {     $taxonomy_page = 'product-range';     $taxonomy_sort_by = 'product-categories';       if (    $q->is_main_query() // target main query          && $q->is_tax( $taxonomy_page ) // target product-range taxonomy term pages     ) {         /**          * there bug in usort never fixed. in instances          * following php warning displayed            * usort(): array modified user comparison function          * @see https://bugs.php.net/bug.php?id=50688           * workaround suppress error reporting          * using @ sign before usort          */               @usort( $posts, function ( $a, $b ) use ( $taxonomy_sort_by )         {             // use term name sorting             $array_a = get_the_terms( $a->id, $taxonomy_sort_by );             $array_b = get_the_terms( $b->id, $taxonomy_sort_by );              // add protection if posts don't have terms, add them last in queue             if ( empty( $array_a ) || is_wp_error( $array_a ) ) {                 $array_a = 'zzz'; // make sure add posts without terms last             } else {                 $array_a = $array_a[0]->name;             }              // add protection if posts don't have terms, add them last in queue             if ( empty( $array_b ) || is_wp_error( $array_b ) ) {                 $array_b = 'zzz'; // make sure add posts without terms last             } else {                 $array_b = $array_b[0]->name;             }              /**              * sort term name, if term name same sort post date              * can adjust sort post title or other wp_post property_exists              */             if ( $array_a != $array_b ) {                  // choose 1 sorting order fits needs                 return strcasecmp( $array_a, $array_b ); // sort term alphabetical asc                  //return strcasecmp( $array_b, $array_a ); // sort term alphabetical desc             } else {                 return $a->post_date < $b->post_date; // not sure comparitor, try >             }         });     }     return $posts; }, 10, 2 );  

edit

here how loop should display page in order in edit

if ( have_posts() ) {     // display range term title     echo '<h1>' . get_queried_object()->name . '</h1>';      // define variable hold term name     $term_name_test = '';      while ( have_posts() ) {     the_post();          global $post;         // terms attached post         $terms = get_the_terms( $post->id, 'product-categories' );         //if don't have terms, give custom name, else, use first term name         if ( empty( $terms ) || is_wp_error( $terms ) ) {             $term_name = 'some custom name fall back';         } else {              $term_name = $terms[0]->name;         }          // display term name before first post in term. test $term_name_test against $term_name         if ( $term_name_test != $term_name ) {             // close our ul tags if $term_name_test != $term_name , if not first post             if ( $wp_query->current_post != 0 )                 echo '</ul>';              echo '<h2>' . $term_name . '</h2>';              // open new ul tag enclose our list             echo '<ul>';         } // endif $term_name_test != $term_name          $term_name_test = $term_name;          echo '<li>' . get_the_title() . '</li>';              // close ul tag on last post                 if ( ( $wp_query->current_post + 1 ) == $wp_query->post_count )              echo '</ul>';      } } 

edit 2

the code above tested , working. on request, here test run on local install. test have used code in op , code.

results

(this results obtained query monitor plugin. also, results include same queries made widgets, nav menus, custom functions etc)

  • code in op -> 318 db queries in 0.7940 s page generation time of 1.1670s. memory usage 12.8mb

  • my code in answer -> 46 db queries in 0.1045 s page generation time of 0.1305s. memory usage 12.6mb

as have stated previously, proof in pudding


Comments