admin管理员组

文章数量:1122846

I need a way to sort the posts on my tag and category archives according to the event date (if it exists) OR post date (if it doesn't).

I have a combined archive for events and posts, but want to list events based on their event_date meta, instead of the date they were posted.

I know I need to update the query to add an "orderby" argument, but can't think of the best way to structure a query argument to get the results I need.

My thinking is that I need to do something like:

foreach($posts as $post) {

    $event_start = get_post_meta($object_id, 'event_start',   TRUE);

    if($event_start) {

        $event_start = strtotime($event_start);
        $list_timestamp_map[$object_id] = $event_start;

        } else {

            $post_date = get_the_date('Y-m-d H:i:s',$object_id);

            $post_date = strtotime($post_date);
            $list_timestamp_map[$object_id] = $post_date;

        }

    }

    arsort($list_timestamp_map);

}

Basically:

  • Check if the "event_start" field has a value
  • If it does, get/use that date
  • If it doesn't, get/use the post date
  • Sort the posts according to that list

But how do I query/compare/sort an existing archive based on a combination of custom field data and post date?

I can't do this:

function rtt_event_sorting( $query ) {

    if( $query->is_main_query() && ( is_category() || is_tag() && empty( $query->query_vars['suppress_filters'] ) ) {

        $query->set('orderby','meta_value');
        $query->set('meta_key','event_start');
        $query->set('orderby','DESC');

        return $query;

    }

}

add_filter( 'pre_get_posts', 'rtt_event_sorting' );

Because if I add a "meta_key" argument it'll return posts based on whether that meta exists or not, not based on its value if it exists and the post date if it doesn't.

I'm probably overthinking it, but what's the best solution here?

I need a way to sort the posts on my tag and category archives according to the event date (if it exists) OR post date (if it doesn't).

I have a combined archive for events and posts, but want to list events based on their event_date meta, instead of the date they were posted.

I know I need to update the query to add an "orderby" argument, but can't think of the best way to structure a query argument to get the results I need.

My thinking is that I need to do something like:

foreach($posts as $post) {

    $event_start = get_post_meta($object_id, 'event_start',   TRUE);

    if($event_start) {

        $event_start = strtotime($event_start);
        $list_timestamp_map[$object_id] = $event_start;

        } else {

            $post_date = get_the_date('Y-m-d H:i:s',$object_id);

            $post_date = strtotime($post_date);
            $list_timestamp_map[$object_id] = $post_date;

        }

    }

    arsort($list_timestamp_map);

}

Basically:

  • Check if the "event_start" field has a value
  • If it does, get/use that date
  • If it doesn't, get/use the post date
  • Sort the posts according to that list

But how do I query/compare/sort an existing archive based on a combination of custom field data and post date?

I can't do this:

function rtt_event_sorting( $query ) {

    if( $query->is_main_query() && ( is_category() || is_tag() && empty( $query->query_vars['suppress_filters'] ) ) {

        $query->set('orderby','meta_value');
        $query->set('meta_key','event_start');
        $query->set('orderby','DESC');

        return $query;

    }

}

add_filter( 'pre_get_posts', 'rtt_event_sorting' );

Because if I add a "meta_key" argument it'll return posts based on whether that meta exists or not, not based on its value if it exists and the post date if it doesn't.

I'm probably overthinking it, but what's the best solution here?

Share Improve this question edited Aug 1, 2019 at 18:07 jongoeson asked Aug 1, 2019 at 17:48 jongoesonjongoeson 635 bronze badges 1
  • Sorry no time for a full answer but I think you'll need your own function for this. Query the posts, iterate through the array and add the meta value to each then write your own sort based on meta if present or post date if not. – jdm2112 Commented Aug 1, 2019 at 19:05
Add a comment  | 

1 Answer 1

Reset to default 0

Based on

  1. Can I exclude a post by meta key using pre_get_posts function? // setting meta in pre_get_posts
  2. Query all posts where a meta key does not exist // exists & not exists formatting
  3. multiple orderby in pre_get_posts action // how to set multiple ordeby

you could perhaps try something like this in your pre_get_posts filter,

//Get original meta query
$meta_query = $query->get('meta_query');

//Add our meta query to the original meta queries
// Posts that have and don't have the meta value
$meta_query[] = array(
  'relation' => 'OR',
  array(
   'key'     => 'event_start',
   'compare' => 'NOT EXISTS',
   'value'   => ''
  ),
  array(
   'key'     => 'event_start',
   'compare' => 'EXISTS'
  )
);
$query->set('meta_query',$meta_query);

$query->set('orderby', array('meta_value' => 'DESC', 'date' => 'DESC'));

My apologies, I couldn't test this code example as I didn't have similar data in any of my WP sandboxes, and it's a bit late as I'm writing this so I might have missed something, so take it with a grain of salt.

本文标签: