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
Post a Comment