I addded attributes to filter out products, based on their selection. For instance, I have field named 'tiled' as yes or no. If person ticks 'yes', all the products with the attribute of 'yes' are shown. All of the products with the attribute of 'no', are not displayed.
How can I display all of the products that are not filtered BELOW the filtered query (ie: showing all of the products with 'No' below the product filter)?
Inside of my functions.php file, I believe this is how the filtered products are queried:
function sort_products_by_positive_attributes($query) {
if (!is_admin() && $query->is_main_query() && is_woocommerce()) {
// First, you would need to get all products along with their positive attributes count
$products_with_scores = [];
if (!empty($query->posts)) {
foreach ($query->posts as $post) {
$product = wc_get_product($post->ID);
$score = get_product_positive_attributes_count($product);
$products_with_scores[$post->ID] = $score;
}
}else {
}
// Then you would sort products by their score
uasort($products_with_scores, function($a, $b) {
return $b - $a;
});
// After sorting, modify the query to order by the IDs in the sorted order
$sorted_ids = array_keys($products_with_scores);
$query->set('orderby', 'post__in');
$query->set('post__in', $sorted_ids);
/*
Query that displays non-filtered products goes here
EDIT: Possible to make an inverted $sorted_ids?
Do second $query here with opposite $sorted_ids?
*/
}
}
//add_action('pre_get_posts', 'sort_products_by_positive_attributes');
function get_product_positive_attributes_count($product) {
// You would implement the logic here to count the number of positive attributes
$score = 0;
// for each attribute, if it's positive, increment $score
return $score;
}
I addded attributes to filter out products, based on their selection. For instance, I have field named 'tiled' as yes or no. If person ticks 'yes', all the products with the attribute of 'yes' are shown. All of the products with the attribute of 'no', are not displayed.
How can I display all of the products that are not filtered BELOW the filtered query (ie: showing all of the products with 'No' below the product filter)?
Inside of my functions.php file, I believe this is how the filtered products are queried:
function sort_products_by_positive_attributes($query) {
if (!is_admin() && $query->is_main_query() && is_woocommerce()) {
// First, you would need to get all products along with their positive attributes count
$products_with_scores = [];
if (!empty($query->posts)) {
foreach ($query->posts as $post) {
$product = wc_get_product($post->ID);
$score = get_product_positive_attributes_count($product);
$products_with_scores[$post->ID] = $score;
}
}else {
}
// Then you would sort products by their score
uasort($products_with_scores, function($a, $b) {
return $b - $a;
});
// After sorting, modify the query to order by the IDs in the sorted order
$sorted_ids = array_keys($products_with_scores);
$query->set('orderby', 'post__in');
$query->set('post__in', $sorted_ids);
/*
Query that displays non-filtered products goes here
EDIT: Possible to make an inverted $sorted_ids?
Do second $query here with opposite $sorted_ids?
*/
}
}
//add_action('pre_get_posts', 'sort_products_by_positive_attributes');
function get_product_positive_attributes_count($product) {
// You would implement the logic here to count the number of positive attributes
$score = 0;
// for each attribute, if it's positive, increment $score
return $score;
}
To display products that do not match the filter ("No" products) below the filtered products ("Yes" products), you can modify your query logic to retrieve both filtered and unfiltered products in a single operation. Here's how to implement it:
Steps:
Modify the Query Logic:
Implementation: Use custom query parameters and manipulate the results before passing them back to WooCommerce.
Updated Code:
Here’s how your sort_products_by_positive_attributes
function can be updated:
function sort_products_by_positive_attributes($query) {
if (!is_admin() && $query->is_main_query() && is_woocommerce()) {
// Get all products matching the filter (e.g., 'tiled' = 'yes')
$filtered_args = [
'post_type' => 'product',
'posts_per_page' => -1, // Adjust as needed
'meta_query' => [
[
'key' => 'tiled', // Replace 'tiled' with your custom field key
'value' => 'yes',
'compare' => '='
]
]
];
$filtered_query = new WP_Query($filtered_args);
// Get all products NOT matching the filter (e.g., 'tiled' = 'no')
$unfiltered_args = [
'post_type' => 'product',
'posts_per_page' => -1, // Adjust as needed
'meta_query' => [
[
'key' => 'tiled', // Replace 'tiled' with your custom field key
'value' => 'no',
'compare' => '='
]
]
];
$unfiltered_query = new WP_Query($unfiltered_args);
// Combine the results: Filtered products first, then unfiltered
$merged_posts = array_merge($filtered_query->posts, $unfiltered_query->posts);
// Set the query posts and post count
$query->posts = $merged_posts;
$query->post_count = count($merged_posts);
}
}
add_action('pre_get_posts', 'sort_products_by_positive_attributes');
Explanation:
Filtered Query:
tiled
is set to yes
.'tiled'
with the actual meta key for your field.Unfiltered Query:
tiled
is set to no
.Merge Results:
$query->posts
.Pagination Support (Optional):
$merged_posts
based on paged
and posts_per_page
.Debugging Tips:
error_log(print_r($query->posts, true));
to verify the merged results.tiled
is correctly assigned to your products in the WooCommerce product meta.This approach ensures that all products are displayed, with the filtered products at the top and the unfiltered ones below. Let me know if further adjustments are needed!