Let users sort posts in WordPress

I’d like to create a page for filtering posts based on a number of criteria.

I can work with wp_query and deliver posts quite easily, my problem is that I can’t figure out (nor can I find any answers online about this, believe me I looked) how to let users do this.

Read More

Take this for example, returns the posts in order of price (custom field meta value) from highest to lowest with 33 posts.

<?php 

$featuredPosts = new WP_Query( array(
'posts_per_page' => 33,
   'meta_key'=>'Price',
   'orderby' => 'meta_value_num',
   'order' => DESC
) );

?>

<?php if ( $featuredPosts->have_posts() ) : ?>

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

<article <?php post_class('item-post block'); ?> id="post-<?php the_ID(); ?>">
<h2 class="price-title"><?php the_title(); ?> </h2>

</article> <!-- end div post -->

<?php endwhile; wp_reset_query(); ?>

<?php endif; ?>

Now, even after reading and googling, I’ll be damned if I can figure out how I’d implement this on the front end for users to filter posts.

I mean, I know you can append to the URLs in WordPress to alter the order of posts, but in this context I’m totally lost.

I tried this, but it doesn’t work.

<?php

$by_price = esc_url(add_query_arg(array(
    'meta_key' => 'price',
    'orderby' => 'meta_value_num',
    'order' => ASC
)));
$by_date = esc_url(add_query_arg(array(
    'orderby' => 'date',
    'order' => DESC
)));

?>

<ul>
    <li><a href="<?php echo $by_price;?>">Order by price</a></li>
    <li><a href="<?php echo $by_date;?>">Order by date</a></li>
</ul>

What I’m trying to achieve is actually quite simple as well, let the user choose the category, choose the price range (guessing I’d write something in JQuery to deliver a value into an field), set the number of results they’d like to be returned.

I’ve tried googling everything under the sun I can think of for this, no dice.

Related posts

Leave a Reply

3 comments

  1. OK, I update the code to make it clear:

    —I do not think meta_key would be auto-pickup—

    functions.php

    ...
    
        $whitList = array(
           'price' => array(
             'posts_per_page' => 33,
             'meta_key'=>'price',
             'orderby'=>'meta_value_num',
             'order' => ASC
           ),
           'date' => array(
             'posts_per_page' => 33,
             'orderby'=>'date',
             'order' => DESC
           )
        );
    ...
    

    Your first loop php:

    <?php 
    
    gloabl $whitList; //to use the $whitList in your functions.php.
    
    $aryQuery = $whitList[$_REQUEST['orderby']] ? $whitList[$_REQUEST['orderby']] : $whitList['price'];
    
    $featuredPosts = new WP_Query( $aryQuery ); 
    
    ....
    ....
    ?>
    

    For your list page:

    <ul>
    <?php
       gloabl $whitList; //to use the $whitList in your functions.php.
       foreach( $whitList as $orderby => $aryOrderBySettings){
          ?>
          <li> <a href="<?php echo esc_url(add_query_arg('orderby', $orderby));?>">Order by <?php echo $orderby;?></a></li>
          <?php
       }
     ?>
    </ul>
    
  2. Using $_GET parameters is the way to go here. First of all you’ll want to allow your visitors access to these add these variables. The link approach is fine, overall, so we can generate augmented links by using the add_query_arg to tack on extra parameters to the current URL.

    <?php
        $urla = add_query_arg( 'sort' => 'price', 'asc' => '1' );
        $urld = add_query_arg( 'sort' => 'price', 'asc' => '0' );
    ?>
    <a href="<?php echo esc_url( $url ); ?>">Sort by price (asc)</a>
    <a href="<?php echo esc_url( $url ); ?>">Sort by price (desc)</a>
    

    When clicked, the tacked on variables can thus be detected:

    <?php
        // Get an allowed sort variable and the order
        $sort = isset( $_GET['sort'] ) && in_array( $_GET['sort'], array( 'price' ) ) )
                ? $_GET['sort'] : null;
        $order = isset( $_GET['asc'] ) && $_GET['asc'] == '0' ? 'DESC' : 'ASC';
    ?>
    

    Now you would augment your main query with the data you just retrieved. If you’re using the default way of querying posts on a page you should be able to get away with query_posts, although it is not recomended. And, if you’re using a custom loop, simply inject the new arguments into it:

    <?php
        $args = array();
        switch ( $sort ):
            case 'price':
                $args['order'] = $order;
                $args['orderby'] = 'meta_value_num';
                $args['meta_key'] = 'price';
                break;
            default:
                break;
        endswitch;
    
        $defaults = array( 'posts_per_page' => 33 );
        $query = new WP_Query( wp_parse_args( $args, $defaults ) );
    ?>
    

    You can add more variables, by creating more URLs and buttons to press, and more cases in the switch statement to extend the basic example above.

    The first piece of code would go wherever you want your buttons to appear. The second piece of code goes before the third one, which goes before outputting the results.