I am trying to get products with a custom field with value condition from DB.
Custom field is named: "_filtered_product".
I want to get products only with value = 1
This is SQL query I have written.
$view_low_filt_sql =
"LEFT JOIN $wpdb->postmeta manage ON (p.ID = manage.post_id AND manage.meta_key = '_manage_stock')
LEFT JOIN $wpdb->postmeta stock ON (p.ID = stock.post_id AND stock.meta_key = '_stock')
LEFT JOIN $wpdb->postmeta threshold ON (p.ID = threshold.post_id AND threshold.meta_key = '_low_inventory_number')
LEFT JOIN $wpdb->postmeta filtered ON (p.ID = filtered.post_id AND filtered.meta_key = '_filtered_product')
WHERE (p.post_type = 'product' OR p.post_type = 'product_variation')
AND (p.post_status = 'publish' OR p.post_status = 'private' OR p.post_status = 'draft')
AND manage.meta_value = 'yes'
AND threshold.meta_value IS NOT NULL
AND filtered.meta_value = '1'
AND IFNULL(CAST(stock.meta_value AS SIGNED),0) <= CAST(threshold.meta_value AS SIGNED)
";
CodePudding user response:
Not sure why you want to write your own sql query
for this simple task, while you could use wp_query
!
That being said, you could use the following snippet to get all products with a specific meta key and meta value:
global $wpdb;
$meta_key = '_filtered_product';
$meta_value = '1';
$sql_statement = "SELECT {$wpdb->prefix}posts.* FROM {$wpdb->prefix}posts INNER JOIN {$wpdb->prefix}postmeta ON ( {$wpdb->prefix}posts.ID = {$wpdb->prefix}postmeta.post_id ) WHERE 1=1 AND ( ( {$wpdb->prefix}postmeta.meta_key = '{$meta_key}' AND {$wpdb->prefix}postmeta.meta_value = '{$meta_value}' ) ) AND {$wpdb->prefix}posts.post_type = 'product' AND ({$wpdb->prefix}posts.post_status = 'publish' OR {$wpdb->prefix}posts.post_status = 'private') GROUP BY {$wpdb->prefix}posts.ID ORDER BY {$wpdb->prefix}posts.post_date DESC";
$sql = $wpdb->prepare($sql_statement);
$sql_results = $wpdb->get_results($sql, ARRAY_A);
if ($sql_results) {
foreach ($sql_results as $result) {
echo "<p>Product id: " . $result['ID'] . " and product title: " . $result['post_title'] . "<p>";
}
} else {
echo "Sorry can't find anything at the moment!";
}
wp_reset_postdata();
Which will output this:
Product id: {the product id} and product title: {the product name that matches the query}
Note:
- The query above, will retrieve all of the data for a product. I just used
ID
andtitle
to give you an example. - If your
$meta_value
is string, then you're all set, meaning I've written the query, assuming that you meta value is string. However, if it's NOT, then use this{$meta_value}
instead of'{$meta_value}'
. - I've used global
$wpdb
and took advantage of its properties and methods. - Instead of hard-coding your database tables prefix which by default would be
wp_
, I've used{$wpdb->prefix}
. - I've also used
$wpdb->prepare
statement to secure the sql statement. - Also, I've used
ARRAY_A
as the second argument in the$wpdb->get_results
function, to get the data as an associative array! - Also, be aware that this query is ordered by date, descending, meaning recent products will get outputted first!
Performing the same query using wp_query
:
$meta_key = '_filtered_product';
$meta_value = '1';
$args = array(
'post_type' => 'product',
'posts_per_page' => -1,
'meta_query' => array(
array(
'key' => $meta_key,
'value' => $meta_value,
'compare' => '=',
)
)
);
$woo_custom_query = new WP_Query($args);
if ($woo_custom_query->have_posts()) {
while ($woo_custom_query->have_posts()) {
$woo_custom_query->the_post();
the_title();
}
} else {
echo "Sorry can't find anything at the moment!";
}
wp_reset_postdata();
This answer has been fully tested on woocommerce 5.x
and works fine!