【问题标题】:Total count for each order item in a loop on WoocommerceWoocommerce 循环中每个订单项目的总计数
【发布时间】:2018-12-21 05:12:28
【问题描述】:

您好,我正在同时学习 PHP 和 Woocommerce! 我正在尝试获取所有具有状态处理的订单以及每个订单的总数并将其显示在页面上。

到目前为止,我可以遍历所有订单并获取每个订单的名称和数量。

但由于我不知道列表中将包含哪种产品,我不确定如何比较名称然后添加数量。

我目前的输出是这样的:

  • prod1 - v1 x 1

  • Prod2 - v3 x 1

  • prod2 - v3 x 1

  • prod3 - v2 x 11

  • prod3 - v2 x 1

我想要的是:

  • prod1 - v1 x 1

  • Prod2 - v3 x 2

  • prod3 - v2 x 12

目前的代码是:

    <?php
/*
Template Name: Print Supplier Order
*/
if (!is_user_logged_in() || !current_user_can('manage_options')) wp_die('This page is private.');
?>
<!DOCTYPE HTML>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title><?php _e('Processing Orders'); ?></title>
    <style>
        body { background:white; color:black; width: 95%; margin: 0 auto; }
    </style>
</head>
<body>
    <header>
        <?php if (have_posts()) : while (have_posts()) : the_post(); ?>

            <h1 class="title"><?php the_title(); ?></h1>

            <?php the_content(); ?>

        <?php endwhile; endif; ?>
    </header>
    <section>
    <?php 

    global $woocommerce;

$args = array( 'post_type' => 'shop_order', 'post_status' => 'wc-processing', 'posts_per_page' => -1 );


    $loop = new WP_Query( $args );

    while ( $loop->have_posts() ) : $loop->the_post();

        $order_id = $loop->post->ID;

        $order = new WC_Order($order_id);

        $product_details = array();
        $order_items = $order->get_items();
        foreach( $order_items as $product ) {
                echo $product['name']." x ".$product['qty'];
                echo '<br>';

            }
        ?>
    <?php endwhile; ?>
    </section>
</body>
</html>

【问题讨论】:

  • $order-&gt;get_items() 返回什么?你能改变这个吗?
  • 它返回当前订单循环的产品数组。我不知道是否有更好的方法来获取这些信息。
  • 虽然可能有更好的方法,但一种解决方案是遍历数组,创建一个新数组,如下所示:$order_items = array(); foreach ($order-&gt;get_items() as $product) { $order_items[$product['name']] += $product['qty']; } foreach ($order_items as $product =&gt; $qty) { echo "$product x $qty &lt;br /&gt;"; }

标签: php sql wordpress woocommerce orders


【解决方案1】:

更新 (现在 SQL 查询还给出了产品名称,使其更轻)

与其使用WP_Query 和一些繁重的代码来进行计算,不如使用这个更轻量级和有效的版本代码,使用WPDB Class(SQL 查询):

global $wpdb;

$results = $wpdb->get_results( "
    SELECT DISTINCT woim2.meta_value as id, SUM(woim.meta_value) as count, woi.order_item_name as name
    FROM {$wpdb->prefix}woocommerce_order_itemmeta as woim
    INNER JOIN {$wpdb->prefix}woocommerce_order_items as woi ON woi.order_item_id = woim.order_item_id
    INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta as woim2 ON woi.order_item_id = woim2.order_item_id
    INNER JOIN {$wpdb->prefix}posts as p ON p.ID = woi.order_id
    WHERE p.post_status IN ('wc-processing','wc-on-hold')
    AND woim.meta_key LIKE '_qty'
    AND woim2.meta_key LIKE '_product_id'
    GROUP BY woim2.meta_value
" );

foreach( $results as $result ){
    echo $result->name . ' (' . $result->id . ') x ' . $result->count . '<br>';
}

产品数量将仅基于处理订单状态,而不是产品总销售额。

经过测试和工作。


获取产品变体 (如您的评论中所要求的)

根据您的评论中要求获取订单中的产品变体,您将替换该行:

 AND woim2.meta_key LIKE '_product_id'

通过以下行:

 AND woim2.meta_key LIKE '_variation_id'

获取所有产品和变体(不包括可变产品)

要获取所有产品,包括产品变体但不包括可变产品,请使用:

global $wpdb;

$results = $wpdb->get_results( "
    SELECT DISTINCT woim2.meta_value as id, SUM(woim.meta_value) as count, woi.order_item_name as name
    FROM {$wpdb->prefix}woocommerce_order_itemmeta as woim
    INNER JOIN {$wpdb->prefix}woocommerce_order_items as woi ON woi.order_item_id = woim.order_item_id
    INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta as woim2 ON woi.order_item_id = woim2.order_item_id
    INNER JOIN {$wpdb->prefix}posts as p ON p.ID = woi.order_id
    WHERE p.post_status IN ('wc-processing','wc-on-hold') 
    AND woim.meta_key LIKE '_qty'
    AND ((woim2.meta_key LIKE '_variation_id' AND woim2.meta_value > 0)
    OR (woim2.meta_key LIKE '_product_id'
    AND woim2.meta_value NOT IN (SELECT DISTINCT post_parent FROM {$wpdb->prefix}posts WHERE post_type LIKE 'product_variation')))
    GROUP BY woim2.meta_value
" );

foreach( $results as $result ){
    echo $result->name . ' (' . $result->id . ') x ' . $result->count . '<br>';
}

经过测试和工作。


全部获取 (即使是产品变体和可变产品)

global $wpdb;

$results = $wpdb->get_results( "
    SELECT DISTINCT woim2.meta_value as id, SUM(woim.meta_value) as count, woi.order_item_name as name
    FROM {$wpdb->prefix}woocommerce_order_itemmeta as woim
    INNER JOIN {$wpdb->prefix}woocommerce_order_items as woi ON woi.order_item_id = woim.order_item_id
    INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta as woim2 ON woi.order_item_id = woim2.order_item_id
    INNER JOIN {$wpdb->prefix}posts as p ON p.ID = woi.order_id
    WHERE p.post_status IN ('wc-processing','wc-on-hold')
    AND woim.meta_key LIKE '_qty'
    AND ((woim2.meta_key LIKE '_variation_id' AND woim2.meta_value > 0)
    OR woim2.meta_key LIKE '_product_id' )
    GROUP BY woim2.meta_value
" );

foreach( $results as $result ){
    echo $result->name . ' (' . $result->id . ') x ' . $result->count . '<br>';
}

经过测试和工作。

【讨论】:

  • 感谢 LoicTheAztec,这看起来很棒,我将如何更改它以便它返回的不是产品而是订购的产品变体?
  • @Adrian 这次你得到了所有可能的情况:1. 所有产品(产品变体除外)...... 2. 只有产品变体...... 3 所有产品(可变产品除外)...... 4. 所有产品(甚至变化和可变产品)......现在您可以选择您需要的东西。我希望它会有用……
  • 这太棒了,谢谢
  • @Adrian 不客气……正如您所见,只要有一点 sql 知识,您就可以以更轻松的方式完成大部分工作。干杯。最后一件事,global $woocommerce; 不是有用且已弃用...如果您需要使用全局 woocommerce 对象,请直接使用 WC(),例如 @ 987654331@、WC()-&gt;customerWC()-&gt;session 等等。
  • 我有很多东西要学!我可能应该将以下内容作为一个新问题,但因为它与答案有关......我还想更新计数中包含的每个订单的状态,因此通过谷歌搜索在 foreach 中添加类似以下内容循环 $order->update_status('pending', 'order_note');但我不认为我有订单 ID 列表吗?
【解决方案2】:

方法一

有几种不同的方法可以解决这个问题,但如果我们只想稍微调整您的代码,那么我们可以通过将产品循环中的产品添加到自定义数组中来实现这一点,使用产品名称作为键,然后遍历该数组。

这是一个例子:

global $woocommerce;

//custom array to list products:
$products_array = array();

//start wp query
$args = array( 
    'post_type'     => 'shop_order', 
    'post_status'   => 'wc-processing', 
    'posts_per_page'=> -1 
);
$loop = new WP_Query( $args );

//loop through orders
while ( $loop->have_posts() ) {
    $loop->the_post();

    //vars
    $order_id           = $loop->post->ID;
    $order              = new WC_Order($order_id);
    $product_details    = array();
    $order_items        = $order->get_items();

    //loop through products
    foreach( $order_items as $product ) {
        //if product has been captured to custom array before, increment value, else add it.
        if (array_key_exists($product['name'], $products_array)) {
            $products_array[$product['name']] += $product['qty'];
        } else {
            $products_array[$product['name']] = $product['qty'];
        }

    }
}

//end wp_query
wp_reset_postdata();

//display list:
foreach ($products_array as $title => $quantity) {
    echo $title.' x '.$quantity;
}

方法二

遍历所有产品,而不是所有订单(一段时间后,假设商店成功,订单可能会比产品多得多,因此从长远来看,这种方法可能会更快)。每个产品都将其总销售额存储为元值,因此访问它非常简单:

//WP Query args
$args = array(
    'post_type'     => 'product',
    'posts_per_page'=> -1,
    'meta_key'      => 'total_sales',
    'orderby'       => 'title',
    'order'         => 'ASC',
    'meta_query'    => array( //make sure we only grab items that have actually sold
        array(
            'key'       => 'total_sales',
            'value'     => 0,
            'compare'   => '>'
        )
    )
);
$query = new WP_Query($args);

//loop through products
if($query->have_posts()) {
    while($query->have_posts()) {
        $query->the_post();
        //use built in Wordpress functions for get_the_title() and get_post_meta()
        echo get_the_title().' x '.get_post_meta(get_the_ID(), 'total_sales', true);
    }
}

//end wp query
wp_reset_postdata();

【讨论】:

    猜你喜欢
    • 2021-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-11
    • 2018-11-17
    • 2019-08-29
    • 2018-11-24
    • 2021-04-16
    相关资源
    最近更新 更多