Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

Here is my problem:

For my articles, I use a custom post type "exhibitions" and posts for all other news. I am displaying them in one query ['post_type' = array('exhibitions','posts')].

The orderby parameter for posts should be their publish date, for exhibitions it should be custom meta value (end date of the project). That way, posts would be displayed in following order:

  1. Exhibition 1 (publish date: 2.1. 2013, end date: 4.4. 2013)
  2. Post 1 (publish date: 13.3. 2013)
  3. Exhibition 2 (publish date: 1.4. 2012, end date: 1.3. 2013)
  4. Post 2 (publish date: 28.2. 2013)

Define PHP variable from date (posts) and end-date meta value (exhibitions) and then sort by it?

I came up with an idea to define PHP variable (end-date meta value for exhibitions, publish date for posts) and sort the wp_query by that.

Am I going in the right direction or not? If so, how to incorporate the variable to wp_query? I've found some related articles/questions, but none of them helped me so far.

Orderby filter?

Orderby filter sounds also as the way to go: Orderby filter @Wordpress.org forums

Thanks!

///

Johaness's solutions is pretty much what I was aiming for. Here is my slightly modified function:

function save_sort_meta( $post_id ) {
$prev_val = get_post_meta( $post_id, 'sort_date', true );
/* set value only if not set yet (i.e. if this is a new post and not an update ) */
if ( 'exhibitions' === $_POST['post_type'] ) {
        $my_meta = get_post_meta( $post_id, '_my_meta', true );
    $datum_end_hidden = $my_meta['datum-end-hidden'];
    update_post_meta( $post_id, 'sort_date', $datum_end_hidden);
} else {
    /* using time() assuming "end_date" is a unix timestamp, adjust if not */
    update_post_meta( $post_id, 'sort_date', time());
}
}
add_action( 'save_post', 'save_sort_meta' );

And here's my query:

$args = array(
'showposts' => '22',
'post_type' => array('post','exhibitions'),
'post_status' => 'publish',
'meta_key' => 'sort_date',
'order' => 'DESC',
'orderby' => 'meta_value_num'
);

For some reason, "post" posts stay in the end of the wp_query (although when I echo custom value "sort_date", it shows correctly and is larger than exhibitions, that should stay "bellow").

Does it have some connection with my removal of checking the update of the post? I did it, because I want to change values on update as well.

Edit: Code above works!

Okay, I found out where was the problem - it's quite embarassing. :) The "end date" meta value of "exhibition" post types was provided by jQuery UI Datepicker - which saves the date in miliseconds.

All I needed to do was to divide $datum_end_hidden by 1000. :)

Thank you VERY MUCH!

share|improve this question

2 Answers 2

up vote 1 down vote accepted

To the best of my knowledge, you cannot sort a query by two different parameters without an additional iteration over the retrieved posts.

Since that ideally should be avoided, let me suggest a different approach:

How about incorporating an additional meta value "sort_date", or the like? And then, in your saving routine, save either the end date of the exhibition or the publish date as "sort_date".

Saving:

function save_sort_meta( $post_id ) {
    $prev_val = get_post_meta( $post_id, 'sort_date', true );
    /* set value only if not set yet (i.e. if this is a new post and not an update ) */
    if ( empty($prev_val) ) {
        if ( 'exhibitions' === $_POST['post_type'] ) {
            update_post_meta( $post_id, 'sort_date', $_POST['end_date'] );
        } else {
            /* using time() assuming "end_date" is a unix timestamp, adjust if not */
            update_post_meta( $post_id, 'sort_date', time() );
        }
    }
}
add_action( 'save_post', 'save_sort_meta' );

The Query:

$args = array(
    'post_status' => 'publish',
    'post_type' = array( 'exhibitions', 'posts' ),
    'meta_key' => 'sort_date',
    'order' => 'DESC',
    'orderby' => 'meta_value_num'
);
$exhibitions_and_posts = new WP_Query( $args );

As an aside, I'd recommend giving the post type a singular name.

share|improve this answer
    
Johannes, this is what I was looking for, thank you very much! Can you check my wp_query arguments in my edited question though? It seems I'm still missing something. –  Petr Cibulka Mar 13 '13 at 10:58
    
Well, the showposts parameter has long (really long) been deprecated, you should use 'posts_per_page' => 22 instead. Other than that, I see nothing wrong. Whether you handle your metadata correctly I cannot say, for I don't know your setup. It however is weird to save (unrelated) meta data as nested associative arrays. Is 'datum_end_hidden' really a key of an array saved under the '_my_meta' meta key? If so, you might want to rethink that in the first place. –  Johannes Pille Mar 13 '13 at 11:06
    
Ok, I found out where was the problem. :) In case you're interested, you can check last edit of my question. THANK YOU VERY MUCH! –  Petr Cibulka Mar 13 '13 at 12:18

I'm not sure if you mean you want to display 2 post types on the same page, both using a different sorting order.

If you are displaying exhibitions on their own archive, such as archive-exhibitions.php, you can set the query for that page to sort by the meta value you define.

$args = array(
    'post_status' => 'publish',
    'post_type' => 'exhibition',
    'meta_key' => 'project_end_date',
    'orderby' => 'meta_value',
    'order' => 'DESC'
);

$my_own_query = new WP_Query($args);

Naturally, change project_end_date to reflect the key name of your project end date meta value. Change orderby to meta_value_num depending on how you save the variable. meta_value is probably fine.

For the Loop, you'll need to use:

<?php if ($my_own_query->have_posts()) : while ($my_own_query->have_posts()) : $my_own_query->the_post(); ?>

Now, loading that archive (http://example.com/exhibitions/) will ignore the regular WP_Query and use your my_own_query for the loop.

share|improve this answer
    
Hi Mark, thanks for your reply, although I did mean to have both post types on the same query. Because of this, Johaness's sollution is more likely what I'm looking for. –  Petr Cibulka Mar 13 '13 at 10:46
2  
As a side comment, in Johaness's solution, you can use add_action( 'wp_insert_post', 'save_sort_meta' ); instead of add_action( 'save_post', 'save_sort_meta' ); if you only want to do this action once, when the post is newly created. If you want to update the meta value every time you update the post, use his action. –  Marc Dingena Mar 13 '13 at 10:56
    
Thanks, that is helpful as well! –  Petr Cibulka Mar 13 '13 at 10:59
    
+1 for the action –  Johannes Pille Mar 13 '13 at 11:08
1  
Sorry, I still don't have enough rep to comment on other posts... Shouldn't !wp_is_post_revision( $post_id ) be added to the save_sort_meta function to prevent bloating wp_postmeta for every autosave WP makes? –  Marc Dingena Mar 13 '13 at 11:52

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.