0

My loop displays featured posts and then posts in reverse chronological order.

However when I use <?php echo get_previous_post(); ?> it grabs posts in reverse chronological order.

How do I add a filter to the previous post function similiar to this but instead filter by an array like this: 'orderby' => array( 'meta_value' => 'DESC', 'date' => 'DESC') ?


Code:


UPDATE: Cleaned up index.php loop after help from @sMyles and @JackJohansson

Index.php loop:

$args = array(
    'posts_per_page'    => - 1,
    'meta_key'          => 'meta-checkbox',
    'orderby'           => array( 'meta_value' => 'DESC', 'date'  =>  'DESC')

);

$posts = new WP_Query( $args );

if($posts->have_posts() ){

    while( $posts->have_posts() ){

        $posts->the_post();

        // Set to content template by default
        $template = 'content';

        // Change template to featured when `is_featured` meta has a value
        if(get_post_meta(get_the_ID(), 'meta-checkbox', 'yes')){
            $template = 'featured';
        }

        // Load template part
        get_template_part( $template, get_post_format() );

    }
}


UPDATE: As suggested, I added where I use the previous post function

Previous Post Function

<div id="next-post">
    <?php $prev_post = get_previous_post();
    if(!empty($prev_post)) {
        echo '<a class="next-story" href="' . get_permalink($prev_post->ID) . '">Next Story</a>'; 
        echo '<a class="next-story-title" href="' . get_permalink($prev_post->ID) . '" title="' . $prev_post->post_title . '">' . $prev_post->post_title . '</a>'; 
    } ?>
</div>


Function For Featured Posts:

function sm_custom_meta() {
    add_meta_box( 'sm_meta', __( 'Featured Posts', 'sm-textdomain' ), 'sm_meta_callback', 'post' );
}
function sm_meta_callback( $post ) {
    $featured = get_post_meta( $post->ID );
?>

<p>
<div class="sm-row-content">
    <label for="meta-checkbox">
        <input type="checkbox" name="meta-checkbox" id="meta-checkbox" value="yes" <?php if ( isset ( $featured['meta-checkbox'] ) ) checked( $featured['meta-checkbox'][0], 'yes' ); ?> />
        <?php _e( 'Featured this post', 'sm-textdomain' )?>
    </label>

</div>
</p>

<?php
}
add_action( 'add_meta_boxes', 'sm_custom_meta' );

function sm_meta_save( $post_id ) {

    // Checks save status
    $is_autosave = wp_is_post_autosave( $post_id );
    $is_revision = wp_is_post_revision( $post_id );
    $is_valid_nonce = ( isset( $_POST[ 'sm_nonce' ] ) && wp_verify_nonce( $_POST[ 'sm_nonce' ], basename( __FILE__ ) ) ) ? 'true' : 'false';

    // Exits script depending on save status
    if ( $is_autosave || $is_revision || !$is_valid_nonce ) {
        return;
    }

    // Checks for input and saves
    if( isset( $_POST[ 'meta-checkbox' ] ) ) {
        update_post_meta( $post_id, 'meta-checkbox', 'yes' );

    } else {
        update_post_meta( $post_id, 'meta-checkbox', '' );
    }

}
add_action( 'save_post', 'sm_meta_save' );
  • Is there any reason in particular that you aren't using the sticky post feature? With sticky posts you could use the original unmodified query and could add an is_sticky() check in your loop to get the appropriate template part. – Dave Romsey Jun 28 '17 at 19:14
  • But that's what exactly sticky posts do. Sticky posts are shown first, then non-sticky posts will be shown. – Jack Johansson Jun 30 '17 at 17:50
  • sticky is a featured just like is_home or is_single. Each post object contains a value that determines whether a post is featured or not. All you need is $post->is_sticky() to check if it's sticky or not. You don't even have to change the loop, sticky posts are always shown first in the loop, unless you set ignore_sticky_posts to 1 in your query's arguments. – Jack Johansson Jun 30 '17 at 17:53
  • @DaveRomsey I believe sticky posts don't change how the get_previous_post function works. From wp-includes/link-template.php: core.trac.wordpress.org/browser/tags/4.8/src/wp-includes/… – Nick M. Jun 30 '17 at 20:08
  • @NickM. Yep, you're right. – Dave Romsey Jun 30 '17 at 20:31
0

You should just do a new full query for all posts (not just featured ones), and set the orderby to meta_value and just check when doing the loop, if that post meta value is yes, and output the featured template, otherwise output standard one.

https://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters

UPDATE: Maybe something like this:

$args = array(
    'posts_per_page'    => - 1,
    'meta_key'          => 'meta-checkbox',
    'orderby'           => array( 'meta_value' => 'DESC', 'date'  =>  'DESC')

);

$posts = new WP_Query( $args );

if($posts->have_posts() ){

    while( $posts->have_posts() ){

        $posts->the_post();

        // Set to content template by default
        $template = 'content';

        // Change template to featured when `is_featured` meta has a value
        if(get_post_meta(get_the_ID(), 'meta-checkbox', true )){
            $template = 'featured';
        }

        // Load template part
        get_template_part( $template, get_post_format() );

    }
}

You will notice I changed the meta key to is_featured .. it's good practice to use underscores instead of hyphens.

To get the value for meta on the post, just use the $post object which has a __get PHP magic method which will return post meta if it exists.

http://php.net/manual/en/language.oop5.overloading.php#object.get

  • Following up on your last comment, I suggest reading this to understand how the queries actually work, as I may have misunderstood your initial question as well: codex.wordpress.org/Query_Overview ... if all you're trying to do is modify the main query that could be handled a lot differently without having to do a custom query, which could be why it's not working for next/prev, ill add another response in a minute for the main query – sMyles Jul 1 '17 at 0:41
  • You also should be careful editing other people's responses, especially if you don't know what you're doing ... as I see you changed part of my code which is incorrect and I had to manually correct – sMyles Jul 1 '17 at 1:09
0

Add this to your child theme's functions.php file to modify the main posts loop query:

add_action( 'pre_get_posts', 'smyles_main_query_custom_orderby' );
/**
 *  Modify main post query sort by meta key and date
 *
 * @param \WP_Query $query
 */
function smyles_main_query_custom_orderby( $query ) {

    // Verify query is main blog archive
    if ( $query->is_home() && $query->is_main_query() ) {
        $query->set( 'meta_key', 'meta-checkbox' );
        $query->set( 'orderby', array( 'meta_value' => 'DESC', 'date' => 'DESC' ) );
    }

}

https://codex.wordpress.org/Plugin_API/Action_Reference/pre_get_posts https://make.wordpress.org/core/2014/08/29/a-more-powerful-order-by-in-wordpress-4-0/

Your index.php file loop can then just look like this:

if ( have_posts() ) {

    while( have_posts() ) {

        the_post();

        $template = get_post_meta( get_the_ID(), 'meta-checkbox', true ) ? 'featured' : 'content';
        // This could have just been the code below had you used underscores like I previously mentioned
        // $template = $post->meta_checkbox ? 'featured' : 'content';

        // Load template part
        get_template_part( $template, get_post_format() );

    }
}
  • That didn't seem to change the get previous post functions @sMyles – Nick M. Jul 6 '17 at 21:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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