This code manually sets the order with the 'order' => 'ASC'
declaration in the WP_Query arguments.
$loop = new WP_Query( array(
'post_type' => 'product',
'meta_key' => 'product_price',
'orderby' => 'meta_value_num',
'order' => 'ASC',
'posts_per_page' => 4,
'paged' => $paged) );
If we want to pass a url parameter to that we could use something like:
'order' => $_GET['posts_order']
along with a url-pattern, like: /?posts_order=ASC
But that would be a terrible idea… because someone could visit the url: /?posts_order=DROP TABLE IF EXISTS table1
& potentially break things.
So, if we’re going to listen for a variable in the url, we’ll want to sanitize it.
<?php
if ( ! empty( $_GET['posts_order'] ) ) {
$posts_order = sanitize_key( $_GET['posts_order'] ); // prevent malicious characters in user-submitted variable
}
or, even better, we can use a whitelist-approach & only allow certain values for
$posts_order="DESC";
if ( ! empty( $_GET['posts_order'] ) ) {
$posts_order_raw = sanitize_key( $_GET['posts_order'] );
if ( 'ASC' === $posts_order_raw ) {
$posts_order="ASC";
}
}
$loop = new WP_Query( array(
'post_type' => 'product',
'meta_key' => 'product_price',
'orderby' => 'meta_value_num',
'order' => $posts_order,
'posts_per_page' => 4,
'paged' => $paged) );
But wait, there’s more!
We could omit the order declaration entirely from the WP_Query
$loop = new WP_Query( array(
'post_type' => 'product',
'meta_key' => 'product_price',
'orderby' => 'meta_value_num',
// 'order' => $posts_order, # Remove this line #
'posts_per_page' => 4,
'paged' => $paged) );
& instead, control the order from the pre_get_posts
hook:
<?php
function wp_se_331547( $wp_query ) {
if ( !is_admin() && is_main_query() ) {
if( 'product' === get_post_type() ) {
$posts_order="DESC";
if ( ! empty( $_GET['posts_order'] ) ) {
$posts_order_raw = sanitize_key( $_GET['posts_order'] );
if ( 'ASC' === $posts_order_raw ) {
$posts_order="ASC";
}
}
$wp_query->set( 'order', $posts_order );
}
}
}
add_action('pre_get_posts', 'wp_se_331547');