I have about 2000 woocommerce products on my wordpress database, each product has an ACF select field named place which value is local or regional.
My goal is to group by each products by the place meta field so i I thought that following code do the job :
class Search
{
public function __construct()
{
add_action("pre_get_posts", [$this, "filterProducts"]);
add_filter('posts_groupby', [$this, 'groupByFilter'] );
}
public function filterProducts($query){
// ... code
// This where i alter que query
// .. code
return $query;
}
public function groupByFilter($groupby)
{
global $wpdb;
return $wpdb->postmeta . ".meta_key = 'place'";
}
}
But, this not working, and output only one product while the expected result is :
— LOCAL
- product
- product
— REGIONAL
- product
- product
I know foreach over each product is a solution, but for performance reasons i am looking do to it directly throught main query.
NOTE : if it helps, I use timber and in the search.php file I have this piece of code :
$context = Timber::get_context();
$context["posts"] = new TimberPostQuery();
// print the results
dump($context['posts']);
UPDATE :
The sql results output this query :
SELECT 6288gjvs_posts.* FROM 6288gjvs_posts
WHERE 1=1
AND 6288gjvs_posts.post_type = 'product'
AND (6288gjvs_posts.post_status = 'publish'
OR 6288gjvs_posts.post_status = 'acf-disabled'
OR 6288gjvs_posts.post_status = 'complete'
OR 6288gjvs_posts.post_status = 'paid'
OR 6288gjvs_posts.post_status = 'confirmed'
OR 6288gjvs_posts.post_status = 'unpaid'
OR 6288gjvs_posts.post_status = 'pending-confirmation'
OR 6288gjvs_posts.post_status = 'cancelled'
OR 6288gjvs_posts.post_status = 'private')
GROUP BY 6288gjvs_postmeta.meta_key = 'place'
ORDER BY 6288gjvs_posts.menu_order, RAND(1348526234)
Copied it and pasted on phpmyadmin with error output :
#1054 – Champ ‘6288gjvs_postmeta.meta_key’ not known in group statement
So i left join the post meta :
SELECT 6288gjvs_posts.post_title, 6288gjvs_posts.ID, 6288gjvs_postmeta.post_id
FROM 6288gjvs_posts
LEFT JOIN 6288gjvs_postmeta
ON 6288gjvs_posts.ID = 6288gjvs_postmeta.post_id
AND 6288gjvs_posts.post_type = 'product'
GROUP BY 6288gjvs_postmeta.meta_key = 'place'
Without success
UPDATE 2
Hello, so finally i opted with two queries, i didn’t found any solution, now I have to manage two paginations in one page :(. If someone find a solution, i always follow up this post and may be useful for others.
Thank you for your helps
2
Answers
If you want to filter your posts by a meta key, you should definitally take a look at WP_Meta_Query.
So like you did with ‘tax_query’ in the ‘pre_get_posts’ filter, you should add another query in the main query like this:
I hope you find this usefull and it solves your problem.
It is a lot easier and advisable to get posts using WP_Query instead of modifying the SQL codes that may affect other post types and queries. In your scenario where you are getting WooCommerce products, use WC_Product_Query. Below is an example that will get you products with
meta_key = place
You can read more about it here – https://github.com/woocommerce/woocommerce/wiki/wc_get_products-and-WC_Product_Query