好的,在这种情况下不使用元数据/属性而不是变体似乎有点奇怪。然而,我做了比这个更不寻常的变化,所以不用判断你的决定:
首先,您必须找到一个合适的动作钩子,它会在订单发生后触发。其中一些是:
更新 2:
我重写了一些改进的代码:
1234563而且我们也知道在可能的情况下使用wc_get_products and WC_Product_Query 是更好的做法。但是在这种情况下,甚至不需要对 db 进行直接后查询,并且可以从 WC_Product_Variable 的 get_available_variations 方法中获得变化
现在它会检查订单项目的数量并将其用于其他日期变化的库存更新。
现在它尽可能使用 WC 类和函数,而不是直接更新元数据、库存数量、库存状态等。
更新后的代码:
add_action('woocommerce_order_status_processing', 'sync_variations_stock');
/**
* Update same date variations on customer order place
* @param $order_id
* @return void
*/
function sync_variations_stock($order_id)
{
if (is_admin()) return; // make sure it's a user order and we aren't on admin dashboard
$order = wc_get_order( $order_id );
foreach( $order->get_items() as $item ) {
if ($item->get_type() !== 'line_item') continue; //if $item is not a product or variation
$order_variation_count = $item->get_quantity();
$order_product_id = $item->get_product_id();
$order_variation_id = $item->get_variation_id();
if ( ! $order_variation_id ) continue; // if the item isn't a variation
$order_variation = wc_get_product($order_variation_id);
$order_variation_attribs = $order_variation->get_variation_attributes();
if ( isset($order_variation_attribs['attribute_pa_date']) ) {
$current_date_attrib = $order_variation_attribs['attribute_pa_date'];
} else {
continue; // stop if the variation in the order doesn't have 'pa_date' attrib
}
$product = wc_get_product( $order_product_id );
$variations = $product->get_available_variations();
foreach ( $variations as $variation ) {
if ( $variation['variation_id'] == $order_variation_id ) {
continue; //if this variation is the one we have in our order
}
if ( ! isset( $variation['attributes']['attribute_pa_color'] ) || !isset( $variation['attributes']['attribute_pa_date'] ) ) {
continue; //if this variation does not have the color or date attrib
}
if ( $variation['attributes']['attribute_pa_date'] == $current_date_attrib ) {
/*
* wc_update_product_stock function sets the stock quantity if the variation stock management is enabled
* NOTE: This function may cause a negative stock even if the variation backorder is set to false
*/
wc_update_product_stock( $variation['variation_id'], $order_variation_count, 'decrease' );
wc_delete_product_transients($variation['variation_id']); // Clear/refresh the variation cache (optionally if needed)
}
}
}
}
经过测试并且可以正常工作!
我的第一个答案:
对于这个例子,我将使用最后一个。但是,您应该小心注意这个钩子,因为它会在“WC 感谢页面”的每个页面加载时触发。最好使用以下钩子之一:
woocommerce_order_status_processing
woocommerce_order_status_completed
woocommerce_payment_complete
最终的代码是这样的:
add_action('woocommerce_thankyou', 'sync_variations_stock');
function sync_variations_stock($order_id)
{
$order = wc_get_order( $order_id );
foreach( $order->get_items() as $item ){
$product_id = $item->get_product_id();
$product_variation_id = $item->get_variation_id();
if (!$product_variation_id) return; // if the item isn't a variation
$date_variation = get_post_meta( $product_variation_id, 'attribute_pa_date', true);
$color_variation = get_post_meta( $product_variation_id, 'attribute_pa_color', true);
if ( ! $date_variation && ! $color_variation ) return; //if the variation doesn't have date and color attributes
$args = array(
'post_parent' => $product_id,
'post_type' => 'product_variation',
'posts_per_page' => -1,
'meta_query' => array(
array(
'key' => 'attribute_pa_date',
'value' => $date_variation,
'compare' => '='
),
array(
'key' => 'attribute_pa_color',
'value' => $color_variation,
'compare' => '!='
)
),
);
$other_date_variations = get_posts($args);
if( is_array($other_date_variations) && !empty($other_date_variations) ){
foreach ($other_date_variations as $date_variation) {
// do your stock updating proccess here. (updateStockVariation() as you write in your code)
$variation_id = $date_variation->ID;
$date_variation_stock = (int) get_post_meta( $variation_id, '_stock', true);
if ($date_variation_stock > 0) { //to prevent backorders
$date_variation_stock = $date_variation_stock - 1;
update_post_meta($variation_id, '_stock', $date_variation_stock);
// if the variation is now out-of-stock, set it as so
if ($date_variation_stock === 0) {
update_post_meta($variation_id, '_stock_status', 'outofstock');
wp_set_post_terms( $variation_id, 'outofstock', 'product_visibility', true );
}
}
}
}
}
}
注意:您必须替换 attribute_pa_date 和 attribute_pa_color 以匹配您的属性 slug。
更新 1
在这个主题中还有其他考虑。 WC Variation 库存数量可能会在其他场景和情况下发生变化,例如仪表板上的订单编辑、订单退款、直接产品编辑等。在上线之前,您也必须考虑这些。
正如我所说的那样,可能还有其他方法可以做你想做的事情。但我无法理解您的设置以及您的变体与日期之间的关系。我认为最好在 WB.SE 上提出与方法相关的问题