WooCommerce Hook - Удалить продукт после размещения заказа - PullRequest
0 голосов
/ 19 марта 2020

Я использую самые последние версии WordPress и WooCommerce.

Я знаю, что это может показаться странным вне контекста, но я хочу добавить хук к моим функциям. php, который удаляет определенный товар по идентификатору из заказа после размещения заказа.

Вот что я работаю до сих пор:

add_action('woocommerce_new_order', 'custom_process_order', 10, 1);
function custom_process_order($order_id) {
    $order = new WC_Order( $order_id );
    $items = $order->get_items();
    foreach ($items as $item) {
        if ($item->get_id()==10766) {
          $order->remove_item( $item->get_id() );
        }
    }
    return $order_id;
}

Я пытаюсь удалить продукт с идентификатором 10766 из заказа, если указанный продукт является частью заказа. Я взял это из другого, более старого поста, поэтому сам код может быть не идеальным. Это определенно не работает.

Обновление после некоторых экспериментов:
С помощью Кэмерона Херда я попробовал следующий код:

add_action('woocommerce_new_order', 'custom_process_order', 10, 1);

function custom_process_order($order_id) {
    $order = new WC_Order( $order_id );
    $items = $order->get_items();
    foreach ($items as $item) {
        if ($item->get_id() === 10766) {
            $order->remove_item( $item->get_id() );
        }
    }

    $order->save_items();

    return $order_id;
}

Это выглядело многообещающе, но при нажатии на кнопку проверки Кнопка отправит пустой заказ, а также выдаст пустое сообщение об ошибке WooCommerce, оставив пользователя на странице оформления заказа.

После этого у меня было 2 идеи:
1.) Изменение remove_item на wc_delete_order_item. Я действительно не знаю разницу, и изменение ее, похоже, тоже не имело значения.
2.) Изменение хука так, чтобы это происходило после того, как заказ попал в конец. Я попытался изменить его с woocommerce_new_order на woocommerce_thankyou. Это, однако, сломало страницу благодарности в дополнение к бездействию с заказом.

Вот с чем я сейчас сижу:

add_action('woocommerce_checkout_create_order', 'custom_process_order', 10, 1);

function custom_process_order($order_id) {
    $order = new WC_Order( $order_id );
    $items = $order->get_items();
    foreach ($items as $item) {
        $current_item_id = $item->get_id();
        if ( $current_item_id === 10766) {
            $order->remove_item($current_item_id);
        }
    }

    $order->save_items();

    return $order_id;
}

Все еще ищу рабочий ответ.

Ответы [ 2 ]

1 голос
/ 19 марта 2020

Может быть, так?

function custom_process_order( $order_id ) {
    if( ! $order_id ) return;

    // get order object
    $order = new WC_Order( $order_id );

    // get order items = each product in the order
    $items = $order->get_items();

    foreach ( $items as $item ) {
        $product = wc_get_product( $item['product_id'] );

        if ( $product->get_id() == 10766 ) {
            $order->remove_item( $item->get_id() );
        }
    }

    // Calculate
    $order->calculate_totals();

    // Save
    $order->save();
}
add_action( 'woocommerce_checkout_order_processed', 'custom_process_order', 10, 1 );
1 голос
/ 19 марта 2020

Просмотр кода из abstracts/abstract-wc-order.php, где расположен метод remove_item ... Я вижу, что элементы добавляются в массив с именем items_to_delete. Эта переменная снова появляется в save_items, где для каждого класса элементов, который должен быть удален, вызывается метод delete.

<?php
// abstracts/abstract-wc-order.php

abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {

    /**
     * Remove item from the order.
     *
     * @param int $item_id Item ID to delete.
     * @return false|void
     */
    public function remove_item( $item_id ) {
        $item      = $this->get_item( $item_id, false );
        $items_key = $item ? $this->get_items_key( $item ) : false;

        if ( ! $items_key ) {
            return false;
        }

        // Unset and remove later.
        $this->items_to_delete[] = $item;
        unset( $this->items[ $items_key ][ $item->get_id() ] );
    }

    // ...

    /**
     * Save all order items which are part of this order.
     */
    protected function save_items() {
        $items_changed = false;

        foreach ( $this->items_to_delete as $item ) {
            $item->delete();
            $items_changed = true;
        }
        $this->items_to_delete = array();

        // ...
    }

    // ...
}

Поэтому вы можете попытаться вызвать $order->save_items() после foreach l oop в вашем пользовательском действии:

add_action('woocommerce_new_order', 'custom_process_order', 10, 1);

function custom_process_order($order_id) {
    $order = new WC_Order( $order_id );
    $items = $order->get_items();
    foreach ($items as $item) {
        if ($item->get_id() === 10766) {
            $order->remove_item( $item->get_id() );
        }
    }

    $order->save_items();

    return $order_id;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...