I'm trying to implement a custom filter to display discounted products in my application, ordered by the highest and lowest discount, but it's not working as expected. The products are not displaying correctly, and the page is refreshing instead of using AJAX to load the content dynamically.
Here is the code I'm currently using:
function filter_products_by_discount( $query ) {
if ( ! is_admin() && $query->is_main_query() && isset( $_GET['discount_filter'] ) && ! empty( $_GET['discount_filter'] ) ) {
$discount_filter = $_GET['discount_filter'];
if ( $discount_filter === 'highest' ) {
add_filter( 'posts_orderby', 'orderby_discount_highest' );
} elseif ( $discount_filter === 'lowest' ) {
add_filter( 'posts_orderby', 'orderby_discount_lowest' );
}
}
}
add_action( 'pre_get_posts', 'filter_products_by_discount' );
function orderby_discount_highest( $orderby ) {
return "wc_product_meta._sale_price DESC";
}
function orderby_discount_lowest( $orderby ) {
return "wc_product_meta._sale_price ASC";
}
function discount_filter_shortcode() {
ob_start();
?>
<form method="get" action="">
<select name="discount_filter" onchange="this.form.submit();">
<option value="">Discount Filter</option>
<option value="highest" <?php echo ( isset($_GET['discount_filter']) && $_GET['discount_filter'] == 'highest' ) ? 'selected' : ''; ?>>highest discount</option>
<option value="lowest" <?php echo ( isset($_GET['discount_filter']) && $_GET['discount_filter'] == 'lowest' ) ? 'selected' : ''; ?>>lowest discount</option>
</select>
</form>
<?php
return ob_get_clean();
}
add_shortcode( 'discount_filter', 'discount_filter_shortcode' );
I'm trying to implement a custom filter to display discounted products in my application, ordered by the highest and lowest discount, but it's not working as expected. The products are not displaying correctly, and the page is refreshing instead of using AJAX to load the content dynamically.
Here is the code I'm currently using:
function filter_products_by_discount( $query ) {
if ( ! is_admin() && $query->is_main_query() && isset( $_GET['discount_filter'] ) && ! empty( $_GET['discount_filter'] ) ) {
$discount_filter = $_GET['discount_filter'];
if ( $discount_filter === 'highest' ) {
add_filter( 'posts_orderby', 'orderby_discount_highest' );
} elseif ( $discount_filter === 'lowest' ) {
add_filter( 'posts_orderby', 'orderby_discount_lowest' );
}
}
}
add_action( 'pre_get_posts', 'filter_products_by_discount' );
function orderby_discount_highest( $orderby ) {
return "wc_product_meta._sale_price DESC";
}
function orderby_discount_lowest( $orderby ) {
return "wc_product_meta._sale_price ASC";
}
function discount_filter_shortcode() {
ob_start();
?>
<form method="get" action="">
<select name="discount_filter" onchange="this.form.submit();">
<option value="">Discount Filter</option>
<option value="highest" <?php echo ( isset($_GET['discount_filter']) && $_GET['discount_filter'] == 'highest' ) ? 'selected' : ''; ?>>highest discount</option>
<option value="lowest" <?php echo ( isset($_GET['discount_filter']) && $_GET['discount_filter'] == 'lowest' ) ? 'selected' : ''; ?>>lowest discount</option>
</select>
</form>
<?php
return ob_get_clean();
}
add_shortcode( 'discount_filter', 'discount_filter_shortcode' );
Share
Improve this question
asked Feb 5 at 15:12
user22774038user22774038
811 silver badge5 bronze badges
2 Answers
Reset to default 2Correcting the pre_get_posts Query
function filter_products_by_discount( $query ) {
if ( ! is_admin() && $query->is_main_query() && isset( $_GET['discount_filter'] ) && ! empty( $_GET['discount_filter'] ) ) {
$discount_filter = $_GET['discount_filter'];
$query->set( 'meta_query', array(
'relation' => 'AND',
array(
'key' => '_regular_price',
'compare' => 'EXISTS'
),
array(
'key' => '_sale_price',
'compare' => 'EXISTS'
),
));
if ( $discount_filter === 'highest' ) {
$query->set( 'orderby', 'meta_value_num' );
$query->set( 'meta_key', '_sale_price' );
$query->set( 'order', 'DESC' );
} elseif ( $discount_filter === 'lowest' ) {
$query->set( 'orderby', 'meta_value_num' );
$query->set( 'meta_key', '_sale_price' );
$query->set( 'order', 'ASC' );
}
}
}
add_action( 'pre_get_posts', 'filter_products_by_discount' );
Modify your form to use AJAX instead of reloading the page:
function discount_filter_shortcode() {
ob_start();
?>
<form id="discount-filter-form">
<select name="discount_filter" id="discount_filter">
<option value="">Discount Filter</option>
<option value="highest" <?php echo ( isset($_GET['discount_filter']) && $_GET['discount_filter'] == 'highest' ) ? 'selected' : ''; ?>>Highest Discount</option>
<option value="lowest" <?php echo ( isset($_GET['discount_filter']) && $_GET['discount_filter'] == 'lowest' ) ? 'selected' : ''; ?>>Lowest Discount</option>
</select>
</form>
<script>
jQuery(document).ready(function($) {
$('#discount_filter').change(function() {
let filterValue = $(this).val();
$.ajax({
url: window.location.href,
type: 'GET',
data: { discount_filter: filterValue },
success: function(response) {
let newContent = $(response).find('.products'); // Adjust selector as needed
$('.products').html(newContent.html());
}
});
});
});
</script>
<?php
return ob_get_clean();
}
add_shortcode( 'discount_filter', 'discount_filter_shortcode' );
Improved pre_get_posts Function
function filter_products_by_discount( $query ) {
if ( ! is_admin() && $query->is_main_query() && isset( $_GET['discount_filter'] ) && ! empty( $_GET['discount_filter'] ) ) {
global $wpdb;
$discount_filter = $_GET['discount_filter'];
// Custom ordering based on discount percentage
$query->set( 'meta_query', array(
'relation' => 'AND',
array(
'key' => '_regular_price',
'compare' => 'EXISTS'
),
array(
'key' => '_sale_price',
'compare' => 'EXISTS'
),
));
// Custom SQL order
$orderby_sql = "( (meta_value+0 - meta_value_num+0) / meta_value+0 ) * 100";
if ( $discount_filter === 'highest' ) {
$query->set( 'orderby', $orderby_sql );
$query->set( 'order', 'DESC' );
} elseif ( $discount_filter === 'lowest' ) {
$query->set( 'orderby', $orderby_sql );
$query->set( 'order', 'ASC' );
}
}
}
add_action( 'pre_get_posts', 'filter_products_by_discount' );
AJAX Support for Instant Filtering (No Page Reload)
function discount_filter_shortcode() {
ob_start();
?>
<form id="discount-filter-form">
<select name="discount_filter" id="discount_filter">
<option value="">Sort by Discount</option>
<option value="highest" <?php echo ( isset($_GET['discount_filter']) && $_GET['discount_filter'] == 'highest' ) ? 'selected' : ''; ?>>Highest Discount</option>
<option value="lowest" <?php echo ( isset($_GET['discount_filter']) && $_GET['discount_filter'] == 'lowest' ) ? 'selected' : ''; ?>>Lowest Discount</option>
</select>
</form>
<script>
jQuery(document).ready(function($) {
$('#discount_filter').change(function() {
let filterValue = $(this).val();
$.ajax({
url: window.location.href,
type: 'GET',
data: { discount_filter: filterValue },
success: function(response) {
let newContent = $(response).find('.products'); // Adjust selector as needed
$('.products').html(newContent.html());
}
});
});
});
</script>
<?php
return ob_get_clean();
}
add_shortcode( 'discount_filter', 'discount_filter_shortcode' );