3
\$\begingroup\$

I've got this code to work, but being really new to PHP, I don't know if this is proper. I've sorted a CPT loop by a custom date.

  1. I'm displaying items from most recent (or future date) to oldest
  2. if the custom date is in the future I display an additional HTML element that says Coming Soon. I've used strtotime for the custom date and compared it to today.

I'm most interested in knowing a better method for converting and comparing time, and if this loop is a proper method of using orderby with a custom date.

get_field() is from the Advanced Custom Fields WordPress plugin.

<?php

    //Loop arguments

    $today = date('Ymd');
    $args = array(
                'post_type' => 'release',
                'showposts' => 6,
                'meta_key'  => 'release_date',
                'orderby'   => 'meta_value_num', // orderby meta field date
                'order'     => 'DESC'
            );
    // query and loop
    $release_query = new WP_Query( $args );

    // $release_date = get_field('release_date');

    while ( $release_query->have_posts() ) : $release_query->the_post();
    // don't duplicate featured posts
    if ( in_array($post->ID, $do_not_duplicate) ) continue;
        update_post_caches( $posts );
?>
    <li class="grid large-4 medium-6 small-12 columns">
    <div class="cd"
        <?php 

            $image = get_field('cd_cover');

            if( !empty($image) ): ?>

                <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>"><img src="<?php echo $image['url']; ?>" alt="<?php echo $image['alt']; ?>" /></a>

            <?php endif; ?>
        <h2>
            <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>">
                <?php the_title(); ?>
            </a>
        </h2>
        <?php 
        $cd_date = get_field('release_date');
        $release_date = date('Ymd', strtotime($cd_date)); // convert custom date to something manageable?
        if ( $release_date > $today ) {
            echo '<p class="soon"><span>Coming Soon!</span></p>';
        } 

        ?>
        </div><!-- /cd -->
    </li>

    <?php 
        //release loop ends
        endwhile;
        // reset
        wp_reset_postdata();
    ?>
\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

I do know nothing about WordPress, so I will not be able to answer if the loop is a proper method for using order by.

Converting and comparing time

The DateTime class has great utilities for exactly this kind of thing. You have DateTime::createFromFormat to use your custom format, DateTime->format for formatting, and DateTime->sub and DateTime->diff for comparing.

Timestamp

For very simple comparing like "is this date bigger than that date," you could use timestamps (AKA time()) and compare them with <> as a timestamp is just a big number (seconds from 1970 until now). This will be more reliable than comparing date strings.

\$\endgroup\$
0
\$\begingroup\$

Few things you could improve. First, don't fetch those duplicate posts at all:

if ( in_array($post->ID, $do_not_duplicate) ) continue;

Instead use the wp_query parameter post__not_in, like this:

$args = array(
    'post_type' => 'release',
    'posts_per_page' => 6,
    'post__not_in' => $do_not_duplicate,
    'meta_key'  => 'release_date',
    'orderby'   => 'meta_value_num', // orderby meta field date
    'order'     => 'DESC'
);

(sidenote: showposts got replaced by posts_per_page, so you should use that)

As you're using the_permalink() and the_title_attribute() twice, put them in a variable and get a minor performance boost.

$image = get_field('cd_cover');
$permalink = get_the_permalink();
$title_attribute = the_title_attribute("", "", false); // return instead of echoing

if( !empty($image) ): ?>

<a href="<?php echo $permalink; ?>" title="<?php echo $title_attribute; ?>"><img src="<?php echo $image['url']; ?>" alt="<?php echo $image['alt']; ?>" /></a>

<?php endif; ?>

<h2>
    <a href="<?php echo $permalink; ?>" title="<?php echo $title_attribute; ?>">
        <?php the_title(); ?>
    </a>
</h2>

Since you're using $cd_date & release date only once, no need to store in extra variables (if you use them more than once, feel free to ignore this)

if ( date('Ymd', strtotime($cd_date)) > get_field('release_date') ) {
    echo '<p class="soon"><span>Coming Soon!</span></p>';
} 

I'm assuming you want to publish those posts immediately and the release_date custom field is for an event of some sort.

So to answer your question: it is a proper method of ordering by numeric meta value, if you're storing those timestamps as strtotime'd numbers and not, for example d-m-Y.

Y-m-d (without dashes of course) would be okay too. It isn't exactly clear in what format you're actually storing the date but strtotime'd timestring is certainly the way you'd want to go. braunbauer gave you a pretty solid answer for converting and comparing time, but on this one you want to take advantage of MySQL functions which you are doing.

To wrap it up:

<?php


$today = date('Ymd');
$args = array(
    'post_type' => 'release',
    'posts_per_page' => 6,
    'post__not_in' => $do_not_duplicate,
    'meta_key'  => 'release_date',
    'orderby'   => 'meta_value_num', // orderby meta field date
    'order'     => 'DESC'
);

$release_query = new WP_Query( $args );


while ( $release_query->have_posts() ) : $release_query->the_post(); 
?>
<li class="grid large-4 medium-6 small-12 columns">
    <div class="cd">
    <?php 

    $image = get_field('cd_cover');
    $title_attribute = the_title_attribute("", "", false); // return instead of echoing

    if( !empty($image) ): ?>

    <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>"><img src="<?php echo $image['url']; ?>" alt="<?php echo $image['alt']; ?>" /></a>

    <?php endif; ?>

    <h2>
        <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>">
            <?php the_title(); ?>
        </a>
    </h2>

<?php 
$cd_date = get_field('release_date');
$release_date = date('Ymd', strtotime($cd_date)); // convert custom date to something manageable?

if ( $release_date > $today ) {
    echo '<p class="soon"><span>Coming Soon!</span></p>';
} 

?>
    </div><!-- /cd -->
</li>

<?php 

endwhile;
wp_reset_postdata();
?>
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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