0

I want to give the user the ability to order posts by post date/alphabetically either on ASC or DESC order through a select input on an archive page.

The easy way would be to show two inputs on the front end: one controlling the order_by parameter, and other controlling the order parameter.

But it would be a lot better if it were just one select input field with four options:

  • Latest
  • Oldest
  • Alphabetical A-Z
  • Alphabetical Z-A

I tried cheating, using & inside each option's value, but it gets automatically escaped on the URL.

<form action="">
    <select name="orderby" id="">
        <option value="post_date&order=DESC">Latest</option>
        <option value="post_date&order=ASC">Oldest</option>
        <option value="post_title&order=ASC">Alphabetical A-Z</option>
        <option value="post_title&order=DESC">Alphabetical A-Z</option>
    </select>
    <button>Filter</button>
</form>

This code gives me a URL like this: http://example.com/?orderby=post_date%26order%3DASC

I could do it easily with javascript, or with PHP, but I wanted to know if there was a better solution.

  • How about a simple list with links? I mean, you aren't sending any data, you are just changing the URL. – fuxia Feb 3 at 15:27
  • I'd would be a much better solution I didn't think of, but I also have other filters that must be combined with this one (category and search, to be specific). That's why I chose to use a form. – Cleber F. Sant'ana Feb 3 at 16:42
0

If you only need to use URL query parameters, you should use simple links instead of form.

If you want to use form, but still want to use URL query parameters, you should definitely go with javascript.

But, if you really want to use form and $_POST data, you can use this:

$orderby = isset($_POST['orderby']) ? $_POST['orderby'] : null; 

switch ($orderby) {
    case 'a_to_z':
        $field = 'post_title';
        $sort = 'ASC';
    break;
    case 'z_to_a':
        $field = 'post_title';
         $sort = 'ASC';
    break;
    case 'date_oldest':
        $field = 'post_date';
         $sort = 'ASC';
    break;        
    default:
         $field = 'post_date';
        $sort = 'DESC';
    break;
}
  • I ended up doing something like you've suggested. Thank you. Didn't think about using simple links, much cleaner for simpler contexts! It doesn't work in my case, though, because I have other filtering inputs and they all must be combined when the user clicks a "Filter" button. – Cleber F. Sant'ana Feb 3 at 16:36
0

There are many ways you could proceed. Here is one.

I would defined the four options like this:

function fetch_order_from_form( $query ){
    if( $query->is_page( ThePAGEID ) && $query->is_main_query() && (isset($_POST["orderby"]) && !empty($_POST["orderby"])) ) {
        if( $_POST["orderby"]) == 1){
            $query->set( 'orderby', 'date' );
            $query->set( 'order', 'ASC' );
        }
        elseif( $_POST["orderby"]) ==2 ){
            $query->set( 'orderby', 'date' );
            $query->set( 'order', 'DESC' );
        }
        elseif( $_POST["orderby"]) ==2 ){
            $query->set( 'orderby', 'title' );
            $query->set( 'order', 'ASC' );
        }
        elseif( $_POST["orderby"]) ==2 ){
            $query->set( 'orderby', 'title' );
            $query->set( 'order', 'DESC' );
        }
    }
}
add_action( 'pre_get_posts', 'fetch_order_from_form' );
  • 1
    I ended up doing something like this. Your IF condition seems very complete, I will use it to prevent problems with unset parameters. Very useful answer, thanks. I'll mark hamdirizal's as correct because the suggests some alternate solutions. – Cleber F. Sant'ana Feb 3 at 16:41

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.