Создание и изменение заказов, HPOS
Заказы создаёт не только покупатель на сайте: их заводят по телефону, импортируют из маркетплейса, дополняют трек-номером. Для этого у объекта заказа есть методы изменения. Правило то же, что и у товаров: set_... и save(), никаких прямых запросов к базе.
Создание заказа
// wp-content/plugins/acme-shop/scripts/create-order.php
$order = wc_create_order(['customer_id' => 0]);
$order->add_product(wc_get_product(12), 2);
$order->set_address([
'first_name' => 'Anna',
'last_name' => 'Schmidt',
'email' => 'anna@example.com',
'address_1' => 'Hauptstrasse 5',
'city' => 'Berlin',
'postcode' => '10115',
'country' => 'DE',
], 'billing');
$order->set_payment_method('cod');
$order->calculate_totals();
$order->update_status('processing', 'Заказ принят по телефону.');
echo 'Создан заказ ' . $order->get_id() . PHP_EOL;wc_create_order() создаёт пустой заказ, add_product() добавляет позицию, calculate_totals() считает суммы и налоги. Запустите файл через wp eval-file: заказ на две кружки появится в «WooCommerce → Заказы» в состоянии «Обработка».
Изменение
// wp-content/plugins/acme-shop/scripts/update-order.php
$order = wc_get_order(1024);
$order->set_shipping_city('Hamburg');
$order->set_customer_note('Позвонить за час до доставки.');
$order->save();Как и у товара, изменения попадают в базу только после save(). Если менялись позиции или доставка, перед сохранением вызывают calculate_totals().
Метаданные заказа
Собственные данные — трек-номер, идентификатор во внешней системе — хранят в метаданных:
// wp-content/plugins/acme-shop/includes/orders.php
add_action('woocommerce_order_status_completed', function (int $orderId, WC_Order $order) {
if ($order->get_meta('_acme_tracking') === '') {
$order->update_meta_data('_acme_tracking', 'AB' . $orderId);
$order->save();
}
}, 10, 2);При переводе заказа в «Выполнен» в него записывается трек-номер. Проверка перед записью защищает от повторного срабатывания хука.
Заметки
$order->add_order_note('Трек-номер: AB1024', true);Второй аргумент true делает заметку видимой покупателю: он получит письмо и увидит её в разделе «Мой аккаунт → Заказы». Без него заметка служебная и видна только в панели.
Поиск по метаданным
$orders = wc_get_orders([
'limit' => 1,
'meta_query' => [
['key' => '_acme_tracking', 'value' => 'AB1024'],
],
]);
$order = $orders[0] ?? null;Так находят заказ по номеру из внешней системы — например, когда служба доставки сообщает о вручении.
Правила HPOS
HPOS хранит заказы в собственных таблицах, а не в wp_posts. Отсюда правила:
| Вместо | Используйте |
|---|---|
get_post($orderId) | wc_get_order($orderId) |
get_post_meta($orderId, $key, true) | $order->get_meta($key) |
update_post_meta($orderId, $key, $value) | $order->update_meta_data($key, $value) и save() |
new WP_Query(['post_type' => 'shop_order']) | wc_get_orders([...]) |
get_post_type($id) === 'shop_order' | $order instanceof WC_Order |
Код, который следует этим правилам, работает при любом способе хранения. Именно это обещает объявление совместимости custom_order_tables из урока о плагине.
Возврат
wc_create_refund([
'order_id' => 1024,
'amount' => 9.90,
'reason' => 'Товар повреждён при доставке.',
]);Функция создаёт возврат на указанную сумму. Когда возвращена вся сумма заказа, он переходит в состояние «Возвращён».
Частая ошибка
После update_meta_data() забывают save(). Значение есть в объекте до конца запроса, поэтому в отладке всё выглядит правильно, но в базу оно не попадает. Исключение — хуки вроде woocommerce_checkout_create_order, которые вызываются прямо перед сохранением: там save() выполнит сам WooCommerce.