I want to display the total number of purchases made on my site to my site users; Previously, I wrote the code that displayed the total number of products published on my site, and now I want the code to display the total number of successful purchases from my site to the user.
The code I wrote to display the number of products on my site is as follows:
function product_count_shortcode() {
$count_posts = wp_count_posts( 'product' );
return $count_posts->publish;
}
add_shortcode( 'product_counthalsho', 'product_count_shortcode' );
You will basically have to show the number of orders that have the status completed. Just create a function that will query the order post_type and with the status completed.
You can simply use get_posts and use the php function count the check how many results you have, or use WP_Query that already has a property in the return object that tells you how many orders you have with that status.
Later Edit:
function mrc_total_completed_orders() {
$args = array(
'post_type' => 'order',
'posts_per_page' => -1,
'post_status' => 'completed',
);
$orders = get_posts( $args );
return count( $orders ); }
Or you can use the WC_Order_Query
function mrc_mrc_total_completed_Orders() {
$query = new WC_Order_Query( array(
'limit' => 99999,
'status' => array( 'completed' ),
'return' => 'ids',
) );
$orders = $query->get_orders();
return count( $orders ); }
Also some documentation here
Note that I haven't tested these solutions, but its enough to get you started :)
Usage:
echo mrc_mrc_total_completed_Orders();
Related
I have a condition that sets a custom field (hide_search = yes) when some posts are used. I have done this successfully, but I now want these posts to not appear under search, or not be indexed.
This is the code that I've come across, but I can't get it to work with my intended functionality.
/** Hide all posts that have the Custom Field hide_search=yes set */
function hide_posts( $query ) {
// If a search query is done from a non-admin
if ( $query->is_search && !is_admin() ){
// Get all posts with meta value {key = hide_search && value = yes}
// Identify their Post Category and set it to negative value
// Set Category with ID to -ID
$query->set( 'cat', -1 );
return $query;
}
return $query;
}
add_filter( 'pre_get_posts', 'hide_posts' );
Any help would be appreciated. Open to other solutions, if they are better.
It seems that I've found the answer to my question
here:
The code mentioned in the article is this:
function exclude_nonadvertorial_search($query) {
//only run for the main query and don't run on admin pages
if (!is_admin() && $query->is_main_query()) {
//now check to see if you are on a search results page
if ($query->is_search) {
//get sponsor posts that are NOT advertorials, so we can exclude their IDs from search
$args = array(
//get posts of the custom post type sponsor_post
'post_type' => 'sponsor_post',
//get all posts
'posts_per_page' => -1,
//return an array of post IDs
'fields' => 'ids',
//now check for posts that have a sponsor_post_type that is not 'advertorial'
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'sponsor_post_type',
'value' => 'advertorial',
'compare' => '!='
),
//some posts don't have a sponsor_post_type meta field set, so check for those too
array(
'key' => 'sponsor_post_type',
'compare' => 'NOT EXISTS'
)
)
);
//now get the posts
$excluded_ids = get_posts($args);
//add these post IDs to the 'post__not_in' query parameter
$query->set('post__not_in', $excluded_ids);
}
}
}
add_action('pre_get_posts', 'exclude_nonadvertorial_search');
I am trying to generate a list of available coupons and to display them using a shortcode. I was hoping to generate the list using SQL and not "-1" since that's heavier on the db from what I understand.
The error I get is this: Notice: Array to string conversion
add_shortcode('ac', 'coupon_list' );
function coupon_list() {
// array for coupons, was hoping for a sql query instead but don't know how
$args = array(
'posts_per_page' => -1,
'orderby' => 'title',
'order' => 'asc',
'post_type' => 'shop_coupon',
'post_status' => 'publish',
);
$coupons = get_posts( $args );
$coupon_names = array();
foreach ( $coupons as $coupon ) {
$coupon_name = $coupon->post_title;
array_push( $coupon_names, $coupon_name );
}
// display all available coupons on product page
echo $coupon_names;
}
There are 2 mistakes in your code: You are trying to display an array with echo and when using a shortcode function the data to display requires to be returned (not echoed).
The following function (shortcode), will display a coma separated string of all available coupon codes using a light SQL Query:
add_shortcode('ac', 'available_coupon_codes' );
function available_coupon_codes() {
global $wpdb;
// Get an array of all existing coupon codes
$coupon_codes = $wpdb->get_col("SELECT post_name FROM $wpdb->posts WHERE post_type = 'shop_coupon' AND post_status = 'publish' ORDER BY post_name ASC");
// Display available coupon codes
return implode(', ', $coupon_codes) ; // always use return in a shortcode
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
USAGE:
1) In the WordPress text editor of a post, a custom post or a page:
[ac]
2) On a php file or template:
echo available_coupon_codes();
or
echo do_shortcode('[ac]');
With a WP_Query (like in your code):
add_shortcode('ac', 'coupon_list' );
function coupon_list() {
$coupon_posts = get_posts( array(
'posts_per_page' => -1,
'orderby' => 'name',
'order' => 'asc',
'post_type' => 'shop_coupon',
'post_status' => 'publish',
) );
$coupon_codes = []; // Initializing
foreach( $coupon_posts as $coupon_post) {
$coupon_codes[] = $coupon_post->post_name;
}
// Display available coupon codes
return implode(', ', $coupon_codes) ; // always use return in a shortcode
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
Same usage than the first function
I have an issue with my Woocommerce products. This issue is fixed if I just update the product (edit the product and click in the Update button) with no changes at all.
I have around 2000 products in my site, then I am thinking of doing this using a function in my function.php file.
It should be something like this, I just need the line which update the product.
function update_all_products(){
// getting all products
$products = get_posts( $args );
// Going through all products
foreach ( $products as $key => $value ) {
// the product ID
$product_id = $value->ID;
// update product
update_post_meta...(NEED HELP HERE)...
} //..end foreach
}
// fire the function
update_all_products();
Try the following, that will update your products by 200 each time to avoid problems
(if you have variable products also, the post_type arg will need to be product & product_variation):
add_action( 'woocommerce_loaded', 'update_products_by_x' );
function update_products_by_x(){
$limit = 200;
// getting all products
$products_ids = get_posts( array(
'post_type' => 'product', // or ['product','product_variation'],
'numberposts' => $limit,
'post_status' => 'publish',
'fields' => 'ids',
'meta_query' => array( array(
'key' => '_sync_updated',
'compare' => 'NOT EXISTS',
) )
) );
// Loop through product Ids
foreach ( $products_ids as $product_id ) {
// Get the WC_Product object
$product = wc_get_product($product_id);
// Mark product as updated
$product->update_meta_data( '_sync_updated', true );
$product->save();
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Each time you will browse a page of your site the function will be triggered. processing products by 200 is just more secure and will avoid a timeout or errors.
You can increase that number to 500 for example, setting the $limit to 500
I want to get the processing order count in WooCommerce. I'm using the following code in the Code Snippet plugin but that is working.
if( !function_exists( 'wc_processing_order_count' ) ) {
require_once '../plugins/woocommerce/includes/wc-order-functions.php';
}
// NOTICE! Understand what this does before running.
$result = wc_processing_order_count();
It's returning nothing.
This custom function use a very light SQL query to get the orders count from a specific status:
function get_orders_count_from_status( $status ){
global $wpdb;
// We add 'wc-' prefix when is missing from order staus
$status = 'wc-' . str_replace('wc-', '', $status);
return $wpdb->get_var("
SELECT count(ID) FROM {$wpdb->prefix}posts WHERE post_status LIKE '$status' AND `post_type` LIKE 'shop_order'
");
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Usage example for "processing" orders count:
// Display "processing" orders count
echo get_orders_count_from_status( "processing" );
Both the answers above are way too complicated for something so simple.
Simplest way is this :)
$processing_orders_count = count(wc_get_orders( array(
'status' => 'processing',
'return' => 'ids',
'limit' => -1,
)));
This method could help you. The order is stored as post_type shop_order. So by creating query to get all posts of type shop_order and by passing arguments to get all processing order, you will be able to get those orders
$args = array(
'post_type' => 'shop_order',
'post_status' => 'publish',
'posts_per_page' => -1,
'tax_query' => array(
array(
'taxonomy' => 'shop_order_status',
'field' => 'slug',
'terms' => array('processing')
)
)
);
$loop = new WP_Query( $args );
while ( $loop->have_posts() ){
$loop->the_post();
$order_id = $loop->post->ID;
$order = new WC_Order($order_id);
}
Take a look at: https://github.com/woocommerce/woocommerce/wiki/wc_get_orders-and-WC_Order_Query
That reference really helped me in a similar situation.
Using the WC functions ensures your code is more future proof compared to using a hardcoded query or WP_Query as mentioned in other answers.
I can't get order objects with status of wc-pending / Pending Payment. It simply returns ALL the order objects:
$my_course_query = new WP_Query( array(
'post_type' => 'shop_order',
'post_status' => 'wc-pending',
'posts_per_page' => -1
) );
Your code Is just working perfectly as expected, in frontend, I have test it and it output only orders with **pending status. So I can't tell what is your issue as your question is not detailed.
I have found this note on WordPress WP_Query reference that could be useful:
Note: Ticket #18408 For querying posts in the admin, consider using get_posts() as wp_reset_postdata() might not behave as expected.
In general, I don't use WP_Query() for customer orders but wc_get_orders() (or get_posts() too) this way:
$customer_orders = wc_get_orders( array(
'limit' => -1,
'status' => 'pending'
) );
// Iterating through each Order with pending status
foreach ( $customer_orders as $order ) {
// Going through each current customer order items
foreach($order->get_items() as $item_id => $item_values){
$product_id = $item_values['product_id']; // product ID
// Order Item meta data
$item_meta_data = wc_get_order_item_meta( $item_id );
// Some output
echo '<p>Line total for '.wc_get_order_item_meta( $item_id, '_line_total', true ).'</p><br>';
}
}
This works also just to get the orders objects.
Related documentation: wc_get_orders and WC_Order_Query
I fixed this weird issue by simply using custom query.
Somehow adding 'post_status' => 'wc-pending' doesn't actually change the query, but if I use 'post_status' => 'pending', the query changes.
So what I did was using that custom query and modify pending to wc-pending.
I do have the same issue (returning ALL Orders) while debugging.
Wrapping the debug-code into an action helped outputting the expected data:
add_action( 'init', 'debug_init' );
function debug_init() {
$custom_query_args = array(
"fields" => "ids",
"post_type" => "shop_order",
"post_status" => array('wc-processing'),
"posts_per_page" => "-1",
"offset" => "0",
"date_query" => [
"before" => "2020-09-10 23:59",
"after" => "1970-01-01 00:00",
"inclusive" => "1"
],
"order" => "DESC"
);
$debugQuery = new WP_Query( $custom_query_args );
$order_ids = $debugQuery->posts;
print_r($order_ids);
die();
}