I am currently developing a WordPress project and I am using WooCommerce with WooCommerce Subscriptions plugin to offer subscriptions to my users. I need help on how to get the quantity of a subscription in PHP.
I am using this code to get subscription but I can not retrieve quantity:
$subscriptions = wcs_get_subscriptions( array(
'customer_id' => get_current_user_id(),
'subscription_status' => 'wc-active',
'order_by' => 'DESC',
'subscriptions_per_page' => - 1
) );
When a user purchases a subscription, the user can select the quantity of subscriptions. So I need to get the value of this field:
Your code is correct and wcs_get_subscriptions() is the right and best way to get customer active subscriptions.
But you have missed a something after your code to get the customer subscription item quantity (code commented):
// Get current customer active subscriptions
$subscriptions = wcs_get_subscriptions( array(
'customer_id' => get_current_user_id(),
'subscription_status' => 'wc-active',
'order_by' => 'DESC',
'subscriptions_per_page' => - 1
) );
if ( count( $subscriptions ) > 0 ) {
// Loop through customer subscriptions
foreach ( $subscriptions as $subscription ) {
// Get the initial WC_Order object instance from the subscription
$order = wc_get_order( $subscription->get_parent_id() );
// Loop through order items
foreach ( $order->get_items() as $item ) {
$product = $item->get_product(); // Get the product object instance
// Target only subscriptions products type
if( in_array( $product->get_type(), ['subscription', 'subscription_variation'] ) ) {
$quantity = $item->get_quantity(); // Get the quantity
echo '<p>Quantity: ' . $quantity . '</p>';
}
}
}
}
Tested and works.
Here is my working code try this
$current_user_id = get_current_user_id();
$customer_subscriptions = get_posts( array(
'numberposts' => -1,
'meta_key' => '_customer_user',
'meta_value' => get_current_user_id(), // Or $user_id
'post_type' => 'shop_subscription', // WC orders post type
'post_status' => 'wc-active' // Only orders with status "completed"
) );
And if you want get all post_status subscription then use this
$customer_subscriptions_for_other_cases = get_posts( array(
'numberposts' => -1,
'meta_key' => '_customer_user',
'meta_value' => get_current_user_id(), // Or $user_id
'post_type' => 'shop_subscription', // WC orders post type
'post_status' => array('wc-on-hold','wc-pending-cancel','wc-active') // Only orders with status "completed"
) );
Thanks
Related
I am having trouble getting the data of users who did not order in the last 2 weeks in woocommerce.
this code is pulling only one person data, I need a sql query to poll all users
function has_bought($user_id) {
// Get all customer orders
$customer_orders = get_posts( array(
'numberposts' => -1,
'meta_key' => '_customer_user',
'meta_value' => $user_id,
'post_type' => 'shop_order', // WC orders post type
'post_status' => 'wc-completed' // Only orders with status "completed"
) );
// return "true" when customer has already one order
return count( $customer_orders ) > 0 ? true : false;
}
You can use date_query. try the below code.
function has_bought($user_id) {
// Get all customer orders
$customer_orders = get_posts( array(
'numberposts' => -1,
'meta_key' => '_customer_user',
'meta_value' => $user_id,
'post_type' => 'shop_order', // WC orders post type
'post_status' => 'wc-completed', // Only orders with status "completed"
'date_query' => array(
'after' => date('Y-m-d', strtotime('-14 days'))
)
) );
// return "true" when customer has already one order
return count( $customer_orders ) > 0 ? true : false;
}
I'm writing some code to modify the related products section as follows:
If a product has cross sell products, show those first, and fill up to 4 total products with others from the same category*
Or
If a product has no cross sell products, show 4 products from the same category*
Here's my function to filter the related products so far:
add_filter( 'woocommerce_related_products', 'fivem_add_linked_to_related_products', 9999, 3 );
function fivem_add_linked_to_related_products( $related_posts, $product_id, $args ) {
$product = wc_get_product( $product_id );
$cross_sell_ids = $product->get_cross_sell_ids();
$product_categories = $product->get_category_ids();
// Get cross sell products
$cross_sell_products = get_posts( array(
'post_type' => 'product',
'post_status' => 'publish',
'fields' => 'ids',
'post__in' => $cross_sell_ids,
'posts_per_page' => 4,
'exclude' => array( $product_id ),
));
// Calculate how many filler products are needed
$category_product_count = 4 - count( $cross_sell_products );
// Exclude main product and cross sell products
$excluded_products = array_push( $cross_sell_ids, $product_id );
// Get filler products from same category
$category_products = get_posts( array(
'post_type' => 'product',
'post_status' => 'publish',
'orderby' => 'rand',
'fields' => 'ids',
'post__not_in' => $excluded_products,
'posts_per_page' => $category_product_count,
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'field' => 'id',
'terms' => $product_categories,
'operator' => 'IN',
)
)
));
// Merge cross sell products with filler products
$related_products = array_merge( $cross_sell_products, $category_products );
// Return related products
return $related_products;
}
Currently, the above code mostly works.
If cross-sells are set, it only displays those cross-sell products- ie. does not fill out to 4 total
If no cross-sells are set, it displays products from the same category as expected.
There are two problems I'm trying to solve:
Code above doesn't fill with category products. If I remove the post__not_in and tax_query arguments, it fills out, but obviously not with products from the same category.
I want to show cross-sell products first, then the category-related products. There appears to be another randomization somewhere that mixes the order up, and I can't work out where that comes from.
Any ideas how I can fix this? Thanks in advance.
Code contains
If a product has cross sell products, show those first, and fill up to 4 total products with others from the same category
If a product has no cross sell products, show 4 products from the same category
function filter_woocommerce_related_products( $related_posts, $product_id, $args ) {
// Taxonomy
$taxonomy = 'product_cat';
// Show products
$show_products = 4;
// Get product
$product = wc_get_product( $product_id );
// Get cross sell IDs
$cross_sell_ids = $product->get_cross_sell_ids();
// Calculate how many filler products are needed
$category_product_needed_count = $show_products - count( $cross_sell_ids );
// If category product needed
if ( $category_product_needed_count >= 1 ) {
// Retrieves product term ids for a taxonomy.
$product_cats_ids = wc_get_product_term_ids( $product_id, $taxonomy );
// Get product id(s) from a certain category, by category-id
$product_ids_from_cats_ids = get_posts( array(
'post_type' => 'product',
'numberposts' => $category_product_needed_count,
'post_status' => 'publish',
'fields' => 'ids',
'tax_query' => array(
array(
'taxonomy' => $taxonomy,
'field' => 'id',
'terms' => $product_cats_ids,
'operator' => 'IN',
)
),
));
// Merge array
$related_posts = array_merge( $cross_sell_ids, $product_ids_from_cats_ids );
} else {
// Slice array until show products
$related_posts = array_slice( $cross_sell_ids, 0, $show_products );
}
// Return
return $related_posts;
}
add_filter( 'woocommerce_related_products', 'filter_woocommerce_related_products', 10, 3 );
// Order by
function filter_woocommerce_output_related_products_args( $args ) {
$args['orderby'] = 'id';
$args['order'] = 'ASC';
return $args;
}
add_filter( 'woocommerce_output_related_products_args', 'filter_woocommerce_output_related_products_args', 10, 1 );
I previously implemented a solution to change the user role on registration, but seem to be missing something this time around.
Does anyone out there have a solution for this that still works or be able to point me in the right direction as to what I'm missing or doing wrong?
Does is what I have tried so far.
add_action('woocommerce_thankyou', 'change_user_role_on_order_success');
function change_user_role_on_order_success($order_id ) {
// Get all customer orders
$customer_orders = get_posts( array(
'numberposts' => -1,
'meta_key' => '_customer_user',
'meta_value' => get_current_user_id(),
'post_type' => 'shop_order', // WC orders post type
'post_status' => 'wc-completed' // Only orders with status "completed"
) );
// Count number of orders
$count = count( $customer_orders );
// return "true" when customer has already one order
if ( $count >= 1 ) {
$user = new WP_User( $order->get_user_id() );
// our new role name
$role = 'editor';
//set the new role to our customer
$user->set_role($role);
}
}
Maybe you could try to use the hook woocommerce_order_status_completed instead. It should fire as soon as your customer really completed the order and removes the need for you to check for the status.
function change_user_role_on_order_status_completed( $order_id ) {
$order = new WC_Order( $order_id );
$user_id = $order->user_id;
$total_orders = get_posts( array(
'numberposts' => -1,
'meta_key' => '_customer_user',
'meta_value' => $user_id,
'post_type' => 'shop_order',
) );
if ( $total_orders > 1 ) {
$user = new WP_User( $order->user_id );
// Set role editor
$user->set_role( 'editor' );
}
}
add_action( 'woocommerce_order_status_completed', 'change_user_role_on_order_status_completed', 10, 1 );
I'm trying to get the price of all products on hold (i.e user has placed order but haven't made a payment) by a user in woocommerce.
I have the following code which detects all products on-hold orders by a user
function get_user_on_hold_product_price() {
global $product, $woocommerce;
// GET USER
$current_user = wp_get_current_user();
// GET USER ON-HOLD ORDERS
$customer_orders = get_posts( array(
'numberposts' => -1,
'meta_key' => '_customer_user',
'meta_value' => $current_user->ID,
'post_type' => 'shop_order',
'post_status' => 'wc-on-hold',
) );
I'm not sure what to do from here to get only the total price of all on-hold orders by the user.
Adding/hooking this function to a shortcode, like this;
add_shortcode('get_on-hold_price', 'get_user_on_hold_product_price')
Thanks
To get the total amount of customer "on-hold" orders using a WC_Order_Query for improved usability and compatibility:
add_shortcode('user_on_hold_total', 'get_user_orders_on_hold_total');
function get_user_orders_on_hold_total() {
$total_amount = 0; // Initializing
// Get current user
if( $user = wp_get_current_user() ){
// Get 'on-hold' customer ORDERS
$on_hold_orders = wc_get_orders( array(
'limit' => -1,
'customer_id' => $user->ID,
'status' => 'on-hold',
) );
foreach( $on_hold_orders as $order) {
$total_amount += $order->get_total();
}
}
return $total_amount;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
To get a formatted total amount replace return $total_amount; by return wc_price($total_amount);
Shortcode usage: [user_on_hold_total]
Related documentation: Woocommerce wc_get_orders() and WC_Order_Query
I have the following code and I need to display order data based on seller id or seller name:
$filters = array(
'post_status' => 'published',
'post_type' => 'shop_order',
'posts_per_page' => 200,
'paged' => 1,
'orderby' => 'modified',
'order' => 'ASC',
'author' => $seller_id,
'post_parent' => $order_id
);
$loop = new WP_Query($filters);
while ($loop->have_posts()) {
$loop->the_post();
$order = new WC_Order($loop->post->ID);
foreach ($order->get_items() as $key => $item)
{
$red = $item['product_id'];
$_sku = get_post_meta( $red, '_sku', true );
}
}
The above loop is not showing any sku or price on the invoice section.
How to display order details on author ID (or seller name)?
Thanks
Your main problem is the post_status here: For WooCommerce Orders "published" post_status doesn't exist. The available status for WooCommerce Orders are for example:
'wc-cancelled'
'wc-completed'
'wc-custom-status'
'wc-on-hold'
'wc-pending'
'wc-processing'
'wc-refunded'
You can have different order statuses in an array…
Also 'post_parent' is can't be the order ID as it always have a 0 value
To finish since WooCommerce 3+ Order items are now a WC_Order_Item_Product object (and you need to use available methods to access the properties values).
Last thing, to get the user ID from the user name, you can use WordPress function get_user_by().
So your code will be:
$args = array(
'post_status' => array( 'wc-completed' ), // <=== HERE
'post_type' => 'shop_order',
'posts_per_page' => 200,
'paged' => 1,
'orderby' => 'modified',
'author' => $seller_id
);
$loop = new WP_Query($args);
while ($loop->have_posts()) {
$loop->the_post();
$order_obj = wc_get_order($loop->post->ID);
foreach ($order_obj->get_items() as $item_id => $item_obj)
{
$item_data = $item_obj->get_data(); // Accessing WC_Order_Item_Product object protected data
$product_id = $item_data['product_id']; // Product ID
$product_sku = get_post_meta( $product_id, '_sku', true ); // SKU
// Just for Testing output
echo "Product ID is $product_id - Sku is $product_sku<br>";
}
}
This code is tested and works for WooCommerce 3+
Helpful Answer: How to get WooCommerce order details