If you are running Woocommerce for your online shop, there is a feature where you can set up coupons for your customers to use. If you want your coupons to be used only on certain products in your shop instead of shop-wide, you can also do so. Woocommerce allows you to add products of your choice to certain coupons, so that customers will be able to get discounts when they buy those products, given that they know what the coupon codes for those products are. This feature does not require any Woocommerce extensions, it’s one of Woocommerce core features.
There could be times when you want to allow your customers to filter products in your store and display only the ones that are eligible for coupons. One reason is to encourage your customers to buy those products instead of other products in your store. In my case, a client asks that all products on their store that are eligible for coupons to be shown with a little image that says “discount with coupon”.
Below is the full code snippets along with example of usage.
<?php | |
/* | |
URL: https://wproot.dev/blog/woocommerce-display-all-products-eligible-for-coupons/ | |
*/ | |
$args = array( | |
'posts_per_page' => -1, //show all posts | |
'post_type' => 'shop_coupon', //custom post type | |
'post_status' => 'publish', //published coupons only | |
); | |
$coupons = get_posts( $args ); //array | |
$coupon_ids = array(); | |
foreach ( $coupons as $coupon ) { | |
$coupon_id = $coupon->ID; | |
$expdate = get_post_meta($coupon_id, 'expiry_date', true); | |
$today = date('Y-m-d'); | |
if ( strtotime($expdate) > strtotime($today) ){ | |
array_push( $coupon_ids, $coupon_id ); //push all coupon id into an array | |
} | |
} | |
$n = 1; | |
foreach ( $coupon_ids as $active_coupon_id ) { | |
${'coupon'.$n.'_prod_ids'} = array(); | |
$str = get_post_meta($active_coupon_id, 'product_ids', true); | |
//str is NOT an array, product ids are stored like so: '10,15,24'. | |
${'coupon'.$n.'_prod_ids'} = explode(",",$str); | |
$n++; | |
} | |
$product_ids_with_coupons = array(); | |
$i = 1; | |
while ($i < $n) { | |
foreach ( ${'coupon'.$i.'_prod_ids'} as ${'coupon'.$i.'_prod_id'} ) { | |
array_push($product_ids_with_coupons, ${'coupon'.$i.'_prod_id'}); | |
} | |
$i++; | |
} | |
/* Usage example */ | |
if ( $product->product_type == 'simple' ) { | |
$product_obj = new WC_Product($currentpostid); | |
foreach ( $product_ids_with_coupons as $product_id_with_coupon ) { | |
if ($product_id_with_coupon == $currentpostid) { | |
//do something here like displaying a 'discount with coupon' image | |
break; | |
} | |
} | |
} | |
?> |
Now let’s break that down.
Step 1: Get all published coupons
First we use WordPress get_posts
function to retrieve all published coupons.
$args = array( | |
'posts_per_page' => -1, //show all posts | |
'post_type' => 'shop_coupon', //custom post type | |
'post_status' => 'publish', //published coupons only | |
); | |
$coupons = get_posts( $args ); //array |
Step 2: Get all coupon ID of active coupons
Now the variable $coupons
in the code above contains all data about all the published coupons we have. But we only want coupons that are still active (not yet expired). And we only want the ID of these coupons. So we add this:
$coupon_ids = array(); | |
foreach ( $coupons as $coupon ) { | |
$coupon_id = $coupon->ID; | |
$expdate = get_post_meta($coupon_id, 'expiry_date', true); | |
$today = date('Y-m-d'); | |
if ( strtotime($expdate) > strtotime($today) ){ | |
array_push( $coupon_ids, $coupon_id ); //push all coupon id into an array | |
} | |
} |
Step 3: Get all product ID of products associated to a coupon
From the code above, we now have an array of coupon IDs of all active coupons in the store. Now with each coupon ID we have, we’re going to retrieve all product IDs associated to it. So we do this:
$n = 1; | |
foreach ( $coupon_ids as $active_coupon_id ) { | |
${'coupon'.$n.'_prod_ids'} = array(); | |
$str = get_post_meta($active_coupon_id, 'product_ids', true); | |
//str is NOT an array, product ids are stored like so: '10,15,24'. | |
${'coupon'.$n.'_prod_ids'} = explode(",",$str); | |
$n++; | |
} |
This may not be the cleanest way to do it, but it gets the job done anyhow. Basically what we did above is we loop through active coupon IDs, retrieve product IDs associated to each coupon, and then store those products IDs in a variable, different variable for each coupon. So we got $coupon1_prod_ids
which stores an array of product IDs associated to coupon 1, and then $coupon2_prod_ids
which stores an array of product IDs associated to coupon 2, and so on.
Step 4: Merge all product IDs in Step 3 into a variable
The final step is to merge all the product IDs we got from above into an array variable so that we could use the data to do whatever we want.
$product_ids_with_coupons = array(); | |
$i = 1; | |
while ($i < $n) { | |
foreach ( ${'coupon'.$i.'_prod_ids'} as ${'coupon'.$i.'_prod_id'} ) { | |
array_push($product_ids_with_coupons, ${'coupon'.$i.'_prod_id'}); | |
} | |
$i++; | |
} |
With the code above, all the data we want is now stored in an array called $product_ids_with_coupons
. This array now contains all product ID of products that are eligible for coupons. From here on, you could do things like comparing the ID of the current product in a loop against this array and determine if it matches.
Example
Here’s an example of usage:
if ( $product->product_type == 'simple' ) { | |
$product_obj = new WC_Product($currentpostid); | |
foreach ( $product_ids_with_coupons as $product_id_with_coupon ) { | |
if ($product_id_with_coupon == $currentpostid) { | |
//do something here like displaying a 'discount with coupon' image | |
break; | |
} | |
} | |
} |
If you’ve got a cleaner solution, please feel free to share it.