通过wordpress URL字符串中的元键查询

I feel like I've been all around the web and back again looking for an answer to this and it's really starting to grind my gears.

Not sure if this is the correct way to do it, but I want to add a query_posts array to a URL in the form of a query_arg. This is our query:

query_posts( array( 'meta_key' => 'rank', 'orderby' => 'meta_value_num', 'order' => 'DESC' , 'paged' => $paged,

How do I use add_query_arg to pass that to the URL so as to re-order the posts with that meta_key/query_posts array? I tried this, it doesn't seem to change the order of the posts, there's something I'm missing here.

<a href="<?php echo $by_rank;?>">  Rank </a>
     <?php $by_rank= esc_url(add_query_arg(array('meta_key' => 'rank',  'orderby' => 'meta_value_num', 'order' => 'DESC'))); ?>

The reason I want to add the query vars to the URL string is so users can sort posts on category pages based on the meta_key/meta_value. Sort of in a similar way to doing ?orderby=date, except with a meta_key.

This can be done, right? Because I'm seriously starting to think it's not possible.

From Rahil's answer

<?php
$meta_key = (isset($_GET['meta_key'])) ?
            sanitize_text_field($_GET['meta_key']) : 'rank'; // use default value here ''

$orderby = (isset($_GET['orderby'])) ?
           sanitize_text_field($_GET['orderby']) : 'meta_value_num'; // use default value here ''

$order = (isset($_GET['order'])) ?
         sanitize_text_field($_GET['order']) : 'DESC'; // use default value here ''

$by_rank = esc_url(add_query_arg(array(
    'meta_key' => $meta_key,
    'orderby' => $orderby,
    'order' => $order
)));
?>
<a href="<?php echo $by_rank;?>">  Rank </a>

Put in the values, the same values that work fine with a query_posts array on other pages, posts don't re-order.

You are actually doing add_query_arg fine but echoing the variable before assigning it some value is your problem.

<a href="<?php echo $by_rank;?>">  Rank </a>
--------------------^^^^^^^^ ----->> undefined variable

 <?php $by_rank= esc_url(add_query_arg(array('meta_key' => 'rank',  'orderby' => 'meta_value_num', 'order' => 'DESC'))); ?>
 ------^^^^^^^^ ----> Now its defined.

Change to this: (Remember Code runs from top to bottom)

<?php
$meta_key = (isset($_GET['meta_key'])) ?
            sanitize_text_field($_GET['meta_key']) : ''; // use default value here ''

$orderby = (isset($_GET['orderby'])) ?
           sanitize_text_field($_GET['orderby']) : ''; // use default value here ''

$order = (isset($_GET['order'])) ?
         sanitize_text_field($_GET['order']) : ''; // use default value here ''

$by_rank = esc_url(add_query_arg(array(
    'meta_key' => $meta_key,
    'orderby' => $orderby,
    'order' => $order
)));
?>
<a href="<?php echo $by_rank;?>">  Rank </a>

Now $by_rank has been assigned a value and you can echo it. It will output

/?meta_key=rank&orderby=meta_value_num&order=DESC

Edit:

Now you have to put above variables $meta_key, $orderby and $order to your query_posts() function:

Like this:

query_posts(array(
    'meta_key' => $meta_key,
    'orderby' => $orderby,
    'order' => $order,
    'paged' => $paged
));

Now changing query strings from url will affect the query_posts()

The answer:-

function wpse139657_orderby(){
    if( isset($_GET['orderby']) ){
        $order = $_GET['order'] or 'DESC';
        set_query_var('orderby', 'meta_value_num');
        set_query_var('meta_key', $_GET['orderby']);
        set_query_var('order', $order);
    }
}

add_filter('pre_get_posts','wpse139657_orderby');

Create a pre_get_posts filter and just pass the meta_key name to the URL like so ?orderby=rank