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.

EDIT: Reworded the question for more clarity

I'm trying to sort by custom meta box data, which I am converting to a date using the strtotime function, but I'm having some difficulty.

My chief problem seems to be a catch-22 with the strtotime function. If I use strtotime inside the loop (see below) I cannot use the UNIX time to sort by date. However, if I process the strtotime upon save (in functions.php), I run into a bunch of problems with the meta box updating / not parsing if the user edits the post or re-saves.

Is there a simple solution to this? Here is the code... I just want to order these posts in ascending order by the custom date field (not the posted date).

EDIT: Fixed the array by adding a meta-key - solution still pending

<!-- The args -->
<?php
$args = array(
    "post_type" => "podcasts",
    "meta-key" => "_date",
    "orderby" => "meta_value",
    "order" => "ASC"
    );
?>

<!-- The Query -->
<?php $podcasts = new WP_Query( $args ); ?>

<!-- The Loop -->
<?php if ( $podcasts->have_posts() ) : while ( $podcasts->have_posts() ) : $podcasts->the_post(); ?>

<!-- Convert Date to Date Stamp -->
<?php $podcast_date = get_post_meta($post->ID, '_date', true);?>
<?php $fixed_date = strtotime($podcast_date); ?>

<!-- Content -->

EDIT: Added relevant meta-box code (below) from functions.php Note -- This code does not include the strtotime function anywhere because I'm currently using it on the page template. I could include it here, but I am not sure what to do to allow the user to edit posts / resave. Once the strtotime function runs upon save, wouldn't it change the meta-box date to something like 1327248252? If so, that won't parse the next time that post is saved, creating issues.

// Create podcast Meta boxes

function add_podcast_metaboxes() {
add_meta_box('podcast_info', 'podcast Information', 'podcast_info', 'podcasts',  'normal', 'high');
}

// podcast Meta Box

function podcast_info() {
global $post;

// Noncename needed to verify where the data originated
echo '<input id="podcastmeta_noncename" name="podcastmeta_noncename" type="hidden" value="' .     wp_create_nonce( plugin_basename(__FILE__) ) . '" />';

// Get the data if its already been entered
$week = get_post_meta($post->ID, '_week', true);
$date = get_post_meta($post->ID, '_date', true);
$description = get_post_meta($post->ID, '_description', true);

// Echo out the field
echo '<strong>Week</strong><br /><em>What week of the series is this podcast?</em>';
echo '<input class="widefat" name="_week" type="text" value="' . $week  . '" />';
echo '<strong>Date</strong><br /><em>Enter the Date the podcast was recorded</em>';
echo '<input class="widefat" name="_date" type="text" value="' . $date  . '" />';
echo '<strong>Description</strong><br /><em>Enter the text you would like to display as a description on the media archives list.</em>';
echo '<input class="widefat" name="_description" type="text" value="' . $description  . '" />';

}

// Save the podcast Meta box Data

function save_podcast_meta($post_id, $post) {

// verify this came from the our screen and with proper authorization,
// because save_post can be triggered at other times
if ( !wp_verify_nonce( $_POST['podcastmeta_noncename'], plugin_basename(__FILE__) )) {
return $post->ID;
}

// Is the user allowed to edit the post or page?
if ( !current_user_can( 'edit_post', $post->ID ))
    return $post->ID;

// OK, we're authenticated: we need to find and save the data
// We'll put it into an array to make it easier to loop though.
$podcast_meta['_week'] = $_POST['_week']; 
$podcast_meta['_date'] = $_POST['_date'];
$podcast_meta['_thumbnail'] = $_POST['_thumbnail'];
$podcast_meta['_seriesimg'] = $_POST['_seriesimg'];
$podcast_meta['_description'] = $_POST['_description'];

// Add values of $podcast_meta as custom fields

foreach ($podcast_meta as $key => $value) { // Cycle through the $podcast_meta array!
    if( $post->post_type == 'revision' ) return; // Don't store custom data twice
    $value = implode(',', (array)$value); // If $value is an array, make it a CSV    (unlikely)
    if(get_post_meta($post->ID, $key, FALSE)) { // If the custom field already has a value
        update_post_meta($post->ID, $key, $value);
    } else { // If the custom field doesn't have a value
        add_post_meta($post->ID, $key, $value);
    }
    if(!$value) delete_post_meta($post->ID, $key); // Delete if blank
}

}
add_action('save_post', 'save_podcast_meta', 1, 2); // save the custom fields
share|improve this question

4 Answers 4

up vote 6 down vote accepted

EDIT: Your problem is this:

When you save your meta data, you want the date to be saved as a strtotime() date, but you want it to display the date back in the old Y-m-d format. What you need to do is save it as strtotime() and then when displaying the text back in the input, you need to reverse that strtotime()so it can be displayed properly. You can do it like so:

In your add_podcasts_metaboxes() function, change the line that gets the date to this (assuming the date would always be a UNIX timestamp if there is one set):

$date = get_post_meta( $post->ID, '_date', true );
if( $date != '' )
    $date = date( 'Y-m-d', $date );

And when saving the meta in save_podcast_meta(), do it like you want with strtotime():

$podcast_meta['_date'] = strtotime( $_POST['_date'] );

This would turn the date into a UNIX timestamp in the database, but with the date() function, you can turn that UNIX timestamp back into a date you can use.


You need to specify a meta key, then orderby meta_value like so:

<!-- The args -->
<?php
$args = array(
    "post_type" => "podcasts",
    "meta_key" => "some_meta_key", // Change to the meta key you want to sort by
    "orderby" => "meta_value_num", // This stays as 'meta_value' or 'meta_value_num' (str sorting or numeric sorting)
    "order" => "ASC"
    );
?>

<!-- The Query -->
<?php $podcasts = new WP_Query( $args ); ?>

<!-- The Loop -->
<?php if ( $podcasts->have_posts() ) : while ( $podcasts->have_posts() ) : $podcasts->the_post(); ?>

<!-- Convert Date to Date Stamp -->
<?php $podcast_date = get_post_meta($post->ID, '_date', true);?>
<?php $fixed_date = strtotime($podcast_date); ?>

<!-- Content -->

See this page of the codex for reference: http://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters

EDIT: I see one (possible) problem with your meta box code that you just added. Not 100% sure though!

Try replacing:

echo '<input id="podcastmeta_noncename" name="podcastmeta_noncename" type="hidden" value="' .     wp_create_nonce( plugin_basename(__FILE__) ) . '" />';

with:

wp_nonce_field( plugin_basename( __FILE__ ), 'podcastmeta_noncename' );

I am not sure if this will solve your problem or makes much of a difference, but that's how I do use nonce in my meta boxes (although I believe there is another way to do it to where it will get rid of that Notice if you have WP_DEBUG set to true).

share|improve this answer
1  
also- your date format should be saved as yyyy-mm-dd or it won't order properly. –  Milo Jan 21 '12 at 23:30
    
Good catch with the meta-key, however this doesn't solve my issue. I'm asking about how to make this work with the strtotime function so that I don't have to limit users to yyyy-mm-dd for the date input. There will still be the issue of sorting w/ that format correct? (i.e. 11 will sort before 2) –  timshutes Jan 22 '12 at 5:41
1  
@timshutes - Oh! You can use meta_value_num as the orderby parameter to order by numeric values. Hope that helps! –  Jared Jan 22 '12 at 5:53
2  
@timeshutes then you must also show your metabox save code, so we can see what is going on in that function. –  Hameedullah Khan Jan 22 '12 at 7:11
1  
@timshutes Why not just apply strtotime right before it's saved? Where you grab the value, like this: $podcast_meta['_date'] = strtotime( $_POST['_date'] ); –  Jared Jan 24 '12 at 15:20

The answers above are great. Another useful tactic to keep in mind is that if you already have an array of data you can sort server-side (vs. database-side) using PHP's usort, uasort and uksort.

To do that, you pass the array as the first argument and as it's second give the method a name of a function that is used as a callback later on. You just need to have that function return 1, 0 or -1 to sort by any custom recipe.

share|improve this answer
    
I'm still not getting the answer I'm looking for here... How do I use the strtotime function in functions.php but prevent the issue of edit > re-save? PROBLEM - I process strtotime at save > meta box updates with new UNIX time value > user edits and resaves > new UNIX time value goes through strtotime again but doesn't parse > breaks. –  timshutes Jan 24 '12 at 15:12

You are facing a similar problem I have, and I was trying to work through / manipulate your offered solutions with no results.

I ended up using http://tablesorter.com/docs and querying my meta-box data directly into the table columns. This worked perfectly and also automatically sorts dates appropriately.

Hope this helps...

share|improve this answer
    
I was able to fix my problem with the solution above - reversing the strtotime() function worked beautifully once I got my code all ironed out. I did have to do a little work to make the meta box update without issue. +1 though for a very cool JS plugin. –  timshutes Jun 28 '12 at 19:44

I realize I should put this in my original post - but it's getting very crowded, and this lends itself toward an answer.

I'm looking for something like this:

http://www.designhammer.com/blog/sorting-events-date-using-wordpress-custom-post-types

However, I'm not quite at the php level where I can take what he's doing and apply it to my situation. It seems like he is adding some logic in functions.php where the strtotime function will only fire if the time is in a good format. That would solve my problem and allow me to sort on the front end.

Thoughts?

share|improve this answer

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.