wpalchemy
wpalchemy copied to clipboard
Filtering a custom post type by 2 metabox fields (with 2 separate queries)
I have a custom post type, "news", and am using two different metaboxes with it, defined in meta-setup-spec.php like this:
$news_mb = new WPAlchemy_MetaBox(array(
'id' => 'news_meta',
'title' => 'Item Details',
'template' => get_stylesheet_directory() . '/metaboxes/news_meta.php',
'types' => array('news'),
'mode' => WPALCHEMY_MODE_EXTRACT
));
$date_meta = new WPAlchemy_MetaBox(array(
'id' => 'date_meta',
'title' => 'Date',
'template' => get_stylesheet_directory() . '/metaboxes/date_meta.php',
'priority' => 'high',
'autosave' => TRUE,
'mode' => WPALCHEMY_MODE_EXTRACT,
'types' => array('news')
));
In news_meta.php, I've added an input group containing three radio inputs as follows:
<div class="input-group">
<?php $mb->the_field('content_type'); ?>
<input id="news_radio" type="radio" name="<?php $mb->the_name(); ?>" value="news"<?php $mb->the_radio_state('news')?' checked="checked"':''; ?>/><label>News</label>
<input id="press_radio" type="radio" name="<?php $mb->the_name(); ?>" value="press"<?php $mb->the_radio_state('press')?' checked="checked"':''; ?>/><label>Press</label>
<input id="event_radio" type="radio" name="<?php $mb->the_name(); ?>" value="event"<?php $mb->the_radio_state('event')?' checked="checked"':''; ?> /><label>Event</label>
</div>
$date_meta is using a field, sortdate, that saves dates as YYMMDD (ie, 20160518). In my page template, I have no trouble outputting posts with these args:
$args = array(
'post_type' => 'news',
'post_status' => 'publish',
'meta_key' => 'sortdate',
'orderby' => 'meta_value',
'order' => 'DESC',
'posts_per_page' => -1
);
I'm able to display when I'm filtering on the radio input value with no problems. For example:
<?php
if($wp_query->have_posts()) :
while ($wp_query->have_posts()) : $wp_query->the_post();
global $news_mb;
$news_mb-> the_meta();
$description = $news_mb->get_the_value('description');
?>
<?php if ( 'news' == $news_mb->get_the_value( 'content_type' ) ) : ?>
<div class="flex-item item">
<a target="_blank" href="<?php echo $news_mb->get_the_value('url'); ?>">
<div class="image-container">
<img class="news-logo img-responsive" src="<?php echo $news_mb->get_the_value('logo'); ?>" />
</div>
<h3><?php echo get_the_title(); ?></h3>
<p><?php echo wp_trim_words( $description, $num_words = 30, $more = null ); ?></p>
</a>
</div>
<?php endif; ?>
<?php
endwhile;
endif;
?>
But I'm running into trouble when I need to run two queries at different places in my template. This is the case for posts with the radio input value of "events" - I need to display the first 4 in one part of the template, and all the rest in another. I used the following for $args:
<?php
global $news_mb, $date_meta;
$news_mb->the_meta();
$date_meta->the_meta();
$args = array(
'post_type' => 'news',
'post_status' => 'publish',
'orderby' => 'sortdate',
'order' => 'DESC',
'posts_per_page' => -1,
'meta_query' => array(
'relation' => 'AND',
array(
'key' => $date_meta->get_the_name('sortdate'),
'value' => date("YYMMDD"),
'type' => 'numeric',
'compare' => '>='
),
array(
'key' => $news_mb->get_the_name('content_type'),
'value' => 'event',
'compare' => '='
)
)
);
?>
It's also worth noting that I added another change above, which is to filter sortdate based on date values <= the current date.
For the two separate queries, I tried adding an increment, since this has worked for less complex scenarios in the past:
**QUERY 1:**
<?php
$i = 0;
if($wp_query->have_posts()) :
while ($wp_query->have_posts()) :
$wp_query->the_post();
global $news_mb, $date_meta;
$news_mb->the_meta();
$date_meta->the_meta();
?>
<?php if($i < 4) : ?>
.... the HTML markup/meta values to be used ...
<?php endif; ?>
<?php
$i++;
endwhile;
endif;
?>
**QUERY 2:**
<?php
$i = 0;
if($wp_query->have_posts()) :
while ($wp_query->have_posts()) :
$wp_query->the_post();
global $news_mb, $date_meta;
$news_mb->the_meta();
$date_meta->the_meta();
?>
<?php if($i >= 4) : ?>
.... the HTML markup/meta values to be used ...
<?php endif; ?>
<?php
$i++;
endwhile;
endif;
?>
But no luck. Perhaps I'm trying to change too much at once...but I know everything was working fine until I, a) added the meta_query array to my $args, b) attempted to beef up my sortdate filter by only displaying current/future events, c) adding the increment. Last thing I'll mention: I also tried using two different $args and $wp_query (ie, $args1 for $wp_query1, $args2 for $wp_query2), but to no avail.
What am I doing wrong?
Definitely do incremental changes ...
Also check https://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters
Your orderby
should likely be 'orderby' => 'meta_value'
Are you getting output?
Promo: I assume you are adding press/news/event functionality .. I've written a plugin to do what you are likely attempting to do, and events can be added with minimal effort (in fact I have an extension in the works).
https://wordpress.org/plugins/nooz/
I think I've narrowed down the issue, and it involves 'posts_per_page'.
- When I set it to -1, I get output, although the increment i'm using in my loop doesn't work, and all of the posts appear
- When I set it to 4 or remove 'posts_per_page' altogether from $args, I get no output
- I also noticed that I only get output when I set 'order' to DESC. When I use ASC (which is what I need to use), I get no output
Update: I'm getting the expected output, opting to use conditionals for the date and radio input values inside the loop rather than in $args. I still have one issue, though: this only appears to work when I set 'order' to DESC. Changing the value to ASC outputs nothing in my first loop (intended for posts 1-4), although the second loop (intended for posts 5 and greater) produces the expected output.
I'm now using the following:
<?php
$date = date('Ymd');
$args = array(
'post_type' => 'news',
'post_status' => 'publish',
'meta_key' => 'sortdate',
'orderby' => 'meta_value',
'order' => 'ASC',
'posts_per_page' => -1
);
global $wp_query;
global $post;
$wp_query= null;
$wp_query = new WP_Query($args);
?>
First loop:
<?php
if($wp_query->have_posts()) :
while ($wp_query->have_posts()) : $wp_query->the_post();
global $news_mb, $sortdate;
global $sortdate;
$news_mb->the_meta();
$date_meta->the_meta();
$description = $news_mb->get_the_value('description');
$sortdate = $date_meta->get_the_value('sortdate');
$index = $wp_query->current_post;
?>
<?php if ( $news_mb->get_the_value('content_type') == 'event' && ($index < 4) && ($date <= $sortdate) ) : ?>
<div class="inner-flex-item child-item">
<a target="_blank" href="<?php echo $news_mb->get_the_value('url'); ?>">
<div class="image-container text-center">
<img class="center-block img-responsive" src="<?php echo $news_mb->get_the_value('logo'); ?>" />
</div>
<h3><?php echo get_the_title(); ?></h3>
<p>
<span>
<?php if ($date_meta->get_the_value('date_range') != '') {
echo $date_meta->get_the_value('date_range');
} else {
echo $date_meta->get_the_value('date');
} ?>
</span>
</p>
</a>
</div>
<?php endif; ?>
<?php
endwhile;
endif;
?>
Second loop:
<?php
if($wp_query->have_posts()) :
while ($wp_query->have_posts()) : $wp_query->the_post();
global $news_mb, $date_meta, $sortdate;
$news_mb->the_meta();
$date_meta->the_meta();
$sortdate = $date_meta->get_the_value('sortdate');
$index = $wp_query->current_post;
?>
<?php if ( $news_mb->get_the_value('content_type') == 'event' && ($index >= 4) && ($date <= $sortdate) ) : ?>
<div class="flex-item item child-item">
<a target="_blank" href="<?php echo $news_mb->get_the_value('url'); ?>">
<div class="image-container text-center">
<img class="center-block img-responsive" src="<?php echo $news_mb->get_the_value('logo'); ?>" />
</div>
<h3><?php echo get_the_title(); ?></h3>
<p>
<span>
<?php if ($date_meta->get_the_value('date_range') != '') {
echo $date_meta->get_the_value('date_range');
} else {
echo $date_meta->get_the_value('date');
} ?>
</span>
</p>
</a>
</div>
<?php endif; ?>
<?php
endwhile;
endif;
?>
Am I missing something as to why ASC order isn't working in the first loop? Is this a matter of needing to use wp_reset_postdata()
, wp_reset_query()
, or is it something else entirely?
issue resolved, this can be marked as closed