Skip to content

Instantly share code, notes, and snippets.

@aj-adl aj-adl/query_function.php
Last active Aug 29, 2015

Embed
What would you like to do?
Wine query - find terms based off posts in $a term and then get all matching posts grouped by $b term
<?php
// put these functions in your themes function file or similar (plugin file maybe?)
function find_all_producers_in_this_region( $region_slug ) {
global $post;
/*
* This function is written to work on any page as long as it is supplied the region slug somehow
*
* If this is being displayed/used on a region's archive page, this 1st query is superflous
* as it will be the same as the main query. You would alter this function to work within the main loop
* then call the next function to fetch each producers wines in this region
*
*
*/
$region_args = array(
// not sure if you've used a custom post type, change if you have
'post_type' => 'wine',
'tax_query' => array(
array(
'taxonomy' => 'region',
'field' => 'slug',
'terms' => $region_slug // your term here (the region)
)
)
);
// Make the Query, fetch all posts in this region
$region_query = new WP_Query( $region_args );
if ( ! $region_query->have_posts() ):
// The query did not find any posts (wines) in this region
// Reset just to be sure, probs not necessary
wp_reset_postdata();
return false;
else:
//Setup an empty array for us to place producer ID's into as we go through the loop
$producers_in_this_region = array();
while ( $region_query->have_posts() ):
//standard 'loop' stuff
$region_query->the_post();
/*
* Fetch the terms (producers) for this post (wine).
*
* Even if there is only one term it will still return an array. I'm assuming only 1
* producer per wine, so I'm just using the first index of the array..
*
* For multiple producers per wine create a foreach() to loop through
* $this_wines_producers, instead of using $this_wines_producers[0]
*
*/
$this_wines_producers = wp_get_post_terms( $post->ID, 'producer', array( "fields" => "all" ) );
if ( !empty( $this_wines_producers ) ) {
$producers_in_this_region[] = $this_wines_producers[0]->slug;
}
// end of the loop
endwhile;
// Remove duplicate producers
$producers_in_this_region = array_unique( $producers_in_this_region );
// Sort Alphabetically (case insentive)
sort( $producers_in_this_region, SORT_STRING | SORT_FLAG_CASE );
// Reset post data to not intefere with main/other queries
wp_reset_postdata();
return $producers_in_this_region;
endif;
}
function find_and_render_wines_by_a_producer_in_this_region( $producer_slug, $region_slug ) {
// Make sure we have what we need before we continue
if ( !$region_slug || !$producer_slug ):
// You can decide what to do in the case of an error, this is just here as an example,
// this particular error is pretty unlikely
echo "<p class='error'> There was an error, either the producer or region were not set correctly</p>";
return;
else:
//$region_slug and $producer_slug both have at least SOME value, so lets continue
// This query will only return wines in the current region - if a producer in this region also
// makes / has wines in other regions (not uncommon) then they will not show on this page
// orderby value is menu_value - feel free to change, though many drag + drop post ordering
// plugins use menu_value to set order, so you could impliment that
$producer_args = array(
'post_type' => 'wine',
'orderby' => 'menu_order',
'tax_query' => array(
'relation' => 'AND',
array(
'taxonomy' => 'producer',
'field' => 'slug',
'terms' => $producer_slug
),
array(
'taxonomy' => 'region',
'field' => 'slug',
'terms' => $region_slug
)
)
);
$producer_query = new WP_Query( $producer_args );
if ( $producer_query->have_posts() ) :
// This code runs before the wines loop, so you could use it to output markup only once per producer
// Ideally, you could use it to provide a heading for reach producer, possibly a blurb about them etc
// Replace this markup with whatever you like, this was just what I used for testing purposes
$this_producer = get_term_by( 'slug', $producer_slug, 'producer' );
echo "<h3>".$this_producer->name."</h3>";
// This here is the loop that will put out the wines belonging to this producer in this region
// Change the markup / output etc to whatever you want
// You could even decouple this further so this function only does the querying and you have something
// else ( get_template_part() or another function ) to do the markup
while ( $producer_query->have_posts() ) :
$producer_query->the_post();
// I just used this for testing, put your actual markup here for each wine.
echo "<h4>".get_the_title()."</h4>";
echo the_content();
endwhile;
endif;
wp_reset_postdata();
endif;
}
function wines_in_this_region_grouped_by_producer( $region_slug ){
if ( ! $region_slug ):
echo "<p class='error'> There was an error, no region is specified</p>";
return;
else:
$producers = find_all_producers_in_this_region( $region_slug );
if ( ! $producers ):
// Producers in region query returned no results
echo "<p class='error'> There was an error, no producers were found in this region</p>";
echo "<pre>".print_r( $producers )."</pre>";
return;
else:
// lez do dis
foreach ( $producers as $producer_slug ){
find_and_render_wines_by_a_producer_in_this_region( $producer_slug, $region_slug );
}
endif;
endif;
}
<?php
get_header();
?>
<div id="main-content" class="main-content">
<h1> Welcome to Query Testing Page </h1>
<div id="primary" class="content-area">
<div id="content" class="site-content" role="main">
<?php
// to use in one of your theme's template files
// region slug should be set somehow - main query vars, custom field on the page etc
wines_in_this_region_grouped_by_producer( 'your_region_slug_here' );
?>
</div><!-- #content -->
</div><!-- #primary -->
</div><!-- #main-content -->
<?php
get_sidebar();
get_footer();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.