Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filtering a custom post type by 2 metabox fields (with 2 separate queries) #107

Open
astewes opened this issue May 18, 2016 · 4 comments
Open

Comments

@astewes
Copy link

astewes commented May 18, 2016

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?

@farinspace
Copy link
Owner

farinspace commented May 19, 2016

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/

@astewes
Copy link
Author

astewes commented May 19, 2016

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

@astewes
Copy link
Author

astewes commented May 20, 2016

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?

@astewes
Copy link
Author

astewes commented May 21, 2016

issue resolved, this can be marked as closed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants