wc_get_orders zamiast WP_Query - jak pisać kod zamówień zgodny z HPOS (i przepisać stare snippety)
W functions.php motywu potomnego siedzi snippet z 2019 roku. Pobiera zamówienia przez get_posts( [ 'post_type' => 'shop_order' ] ), wyciąga numer faktury przez get_post_meta() i wysyła raport do księgowości. Działał sześć lat. Po włączeniu HPOS zwraca pustą tablicę, a w trybie zgodności nadal coś zwraca, tylko nieaktualne. Nikt nie widzi błędu, bo błędu nie ma.
Ten wpis jest kontynuacją tekstu o tym, co to jest HPOS i czy warto go włączyć. Tam było "co i czy włączać", tu jest "jak pisać kod, żeby to przeżył". Nie powtarzam opisu czterech tabel, do tego jest tamten wpis. Wszystkie snippety sprawdziłem na WooCommerce 11.0.1 (20 września 2026).
Nie jest to pełny referencer parametrów wc_get_orders(). Ten jest w dokumentacji WooCommerce. Chodzi o to, które wzorce się psują, czym je zastąpić i gdzie leżą pułapki, o których dokumentacja wspomina jednym ostrzeżeniem w ramce.

Krótka odpowiedź (dla niecierpliwych)
wc_get_orders() i WC_Order_Query to jedyny wspierany sposób pobierania zamówień w WooCommerce. Działają tak samo na HPOS i na starym magazynie wpisów, bo to WooCommerce wybiera tabele, nie Twój kod. WP_Query, get_posts(), get_post_meta() i bezpośrednie zapytania $wpdb do wp_posts lub wp_postmeta na HPOS czytają puste albo nieaktualne dane. Do meta zamówienia służy $order->get_meta(), do zapisu $order->update_meta_data() zakończone $order->save().
Cztery zamienniki, które załatwiają większość przypadków:
| Po staremu | Zgodnie z HPOS |
|---|---|
get_post( $order_id ) |
wc_get_order( $order_id ) |
get_post_meta( $id, '_klucz', true ) |
$order->get_meta( '_klucz' ) |
update_post_meta( $id, '_klucz', $v ) |
$order->update_meta_data( '_klucz', $v ); $order->save(); |
new WP_Query( [ 'post_type' => 'shop_order' ] ) |
wc_get_orders( [ ... ] ) |
Pełna tabela, z hookami i metaboxami, jest w sekcji o audycie.
Dlaczego WP_Query i get_post_meta psują się na zamówieniach
WP_Query czyta wp_posts. Na HPOS zamówienia są w wp_wc_orders, a w wp_posts zostaje tylko wpis typu shop_order_placehold, czyli rezerwacja numeru ID bez meta i bez statusu w sensie WooCommerce. Zapytanie z post_type => 'shop_order' zwraca pustą tablicę. Zapytanie z post_type => 'shop_order_placehold' zwraca wydmuszki, z którymi nie da się nic zrobić.
get_post_meta( $order_id, ... ) czyta wp_postmeta. Na HPOS meta zamówień leżą w wp_wc_orders_meta. W trybie zgodności wp_postmeta bywa wypełnione, bo WooCommerce dopisuje tam kopię przy każdym zapisie, więc snippet "działa". Czyta jednak kopię, nie źródło. A od WooCommerce 10.7 zapis po staremu przez update_post_meta() nie wraca już do HPOS, bo sync on read został wyłączony. Dane cicho się rozjeżdżają.
Bezpośrednie $wpdb na wp_posts i wp_postmeta ma ten sam problem, a do tego pęka przy każdej zmianie schematu. Dokumentacja WooCommerce mówi wprost, że autorzy wtyczek i motywów nie powinni pisać własnych zapytań ani surowego SQL do zamówień, bo zmiany w bazie WordPressa i WooCommerce łamią taki kod.
To nie jest nowość z 2023 roku. Obiekt WC_Order i funkcja wc_get_order() istnieją od WooCommerce 3.0 z kwietnia 2017. HPOS zamienił tylko "powinieneś" na "musisz". Kod pisany przez CRUD od 2017 roku przeszedł na HPOS bez jednej zmiany.
Reguła diagnostyczna: jeśli snippet działa na stagingu bez HPOS i "nie działa" na produkcji z HPOS, prawie zawsze szukaj w nim get_post, get_post_meta albo WP_Query.
wc_get_order i wc_get_orders w praktyce
wc_get_orders( $args ) to skrót do WC_Order_Query. Oba przyjmują te same argumenty i zwracają tablicę obiektów WC_Order, albo tablicę ID przy 'return' => 'ids'. Poniżej zapytania, których szuka się najczęściej. Każdy snippet jest kompletny.
Pojedyncze zamówienie
$order = wc_get_order( $order_id );
if ( ! $order ) {
return; // nie ma takiego zamówienia albo ID nie jest zamówieniem
}
$status = $order->get_status(); // 'processing', bez prefiksu wc-
$total = $order->get_total();
$email = $order->get_billing_email();
$date = $order->get_date_created(); // WC_DateTime albo null
$items = $order->get_items();
wc_get_order() zwraca false dla nieistniejącego ID i dla ID, które nie jest zamówieniem. Sprawdzaj to zawsze. I nigdy $order->ID ani $order->post_status: pierwsze na HPOS nie istnieje, drugie nigdy nie było publicznym API. Zamiast tego get_id() i get_status().
Ostatnie zamówienia o danym statusie
$orders = wc_get_orders(
array(
'status' => array( 'processing', 'on-hold' ),
'limit' => 20,
'orderby' => 'date',
'order' => 'DESC',
)
);
Parametr status przyjmuje statusy z prefiksem wc- i bez. Parametr limit bez podania przyjmuje wartość posts_per_page z ustawień czytania, zwykle 10. Wartość -1 oznacza wszystkie zamówienia i tu uwaga: -1 z domyślnym 'return' => 'objects' przy stu tysiącach zamówień ładuje sto tysięcy obiektów do pamięci. Przy masowych operacjach bierz same ID i przetwarzaj partiami:
$page = 1;
do {
$result = wc_get_orders(
array(
'status' => 'completed',
'limit' => 500,
'paged' => $page,
'return' => 'ids',
'paginate' => true,
)
);
foreach ( $result->orders as $order_id ) {
$order = wc_get_order( $order_id );
// przetwarzanie
}
$page++;
} while ( $page <= $result->max_num_pages );
Zamówienia klienta
// Po ID użytkownika.
$orders = wc_get_orders( array( 'customer_id' => 12 ) );
// Po e-mailu rozliczeniowym, także dla gości bez konta.
$orders = wc_get_orders( array( 'customer' => 'jan@example.com' ) );
Parametr customer przyjmuje ID albo e-mail, co załatwia typowe "pokaż historię zamówień gościa".
Zamówienia z zakresu dat
// Utworzone w pierwszym kwartale (daty w strefie sklepu, do końca dnia).
$orders = wc_get_orders( array( 'date_created' => '2026-01-01...2026-03-31' ) );
// Opłacone po 1 czerwca.
$orders = wc_get_orders( array( 'date_paid' => '>2026-06-01' ) );
// Utworzone w ostatniej godzinie (timestamp = UTC, precyzja do sekundy).
$orders = wc_get_orders( array( 'date_created' => '>' . ( time() - HOUR_IN_SECONDS ) ) );
Daty w formacie YYYY-MM-DD są interpretowane w strefie czasowej sklepu, timestampy w UTC. Przy raporcie "za wczoraj" to jest różnica jednej lub dwóch godzin na granicy dnia.
Zamówienia zawierające dany produkt
wc_get_orders() nie ma parametru product_id. Są dwie uczciwe drogi.
Pierwsza, prosta i wolna przy dużej liczbie zamówień: zawęź zapytanie datami i przejdź po pozycjach.
$product_id = 123;
$found = array();
$orders = wc_get_orders(
array(
'date_created' => '>' . ( time() - 30 * DAY_IN_SECONDS ),
'limit' => -1,
'return' => 'ids',
)
);
foreach ( $orders as $order_id ) {
$order = wc_get_order( $order_id );
foreach ( $order->get_items() as $item ) {
if ( $product_id === $item->get_product_id() || $product_id === $item->get_variation_id() ) {
$found[] = $order_id;
break;
}
}
}
Druga: własny parametr zapytania, obsłużony przez filtry WooCommerce. Ten wzorzec opisuję w sekcji o OrderUtil, bo wymaga dwóch ścieżek. Trzecia możliwość, o której warto wiedzieć: tabele pozycji zamówienia (wp_woocommerce_order_items i wp_woocommerce_order_itemmeta) nie zmieniły się wraz z HPOS i są wspólne dla obu magazynów, więc własny SQL z $wpdb->prepare() jest tam technicznie poprawny.
Zwroty
$refunds = wc_get_orders(
array(
'type' => 'shop_order_refund',
'date_created' => '>' . ( time() - DAY_IN_SECONDS ),
)
);
Zwrot jest osobnym obiektem, a jego parent to ID zamówienia.
Meta zamówienia: get_meta, update_meta_data i save

Wzorzec z recipe book HPOS:
$order = wc_get_order( $order_id );
if ( ! $order ) {
return;
}
$order->update_meta_data( '_numer_faktury', 'FV/2026/09/0142' );
$order->add_meta_data( '_log_integracji', 'wyslano', true );
$order->delete_meta_data( '_tymczasowy_token' );
$order->save();
$numer = $order->get_meta( '_numer_faktury' ); // jedna wartość
$logi = $order->get_meta( '_log_integracji', false ); // tablica wszystkich wartości
WooCommerce sam decyduje, czy zapisać do wp_wc_orders_meta, czy do wp_postmeta. Trzy pułapki.
save() jest kosztowne i dokumentacja mówi to wprost. Jedno save() na końcu przepływu, nie po każdym update_meta_data(). W hooku woocommerce_checkout_create_order dostajesz obiekt przed pierwszym zapisem: ustaw meta i nie wołaj save() w ogóle, WooCommerce zrobi to za chwilę sam.
Klucze zaczynające się od podkreślenia są "chronione": nie pokazują się w metaboxie pól niestandardowych. To to samo zachowanie, co przy zwykłych postach, i w HPOS nadal obowiązuje.
Nie mieszaj dwóch API w jednym żądaniu. Po update_post_meta() obiekt WC_Order załadowany wcześniej w tym samym żądaniu nadal ma starą wartość w pamięci. Jeśli w sklepie jest kod, który zapisuje po staremu, a drugi czyta przez get_meta(), dostaniesz dwa różne wyniki dla tego samego zamówienia.
Istnieje też wzorzec odczytu meta bez ładowania całego obiektu, przydatny przy tysiącach zamówień: sprawdzasz magazyn przez OrderUtil i pytasz bezpośrednio wp_wc_orders_meta albo get_post_meta(). Traktuj to jako optymalizację na konkretny przypadek, nie jako domyślną drogę. Domyślnie wc_get_order()->get_meta().
Zapytania po meta i polach: meta_query, field_query, date_query
Od WooCommerce 8.2 wc_get_orders() przyjmuje trzy argumenty o składni identycznej jak w WP_Query, opisane w osobnej stronie dokumentacji.
meta_query, na przykład "zamówienia, które nie mają jeszcze numeru faktury":
$orders = wc_get_orders(
array(
'status' => 'completed',
'limit' => -1,
'return' => 'ids',
'meta_query' => array(
array(
'key' => '_numer_faktury',
'compare' => 'NOT EXISTS',
),
),
)
);
field_query, czyli operatory i zagnieżdżenia na polach zamówienia. Wcześniej wymagało to własnego SQL:
$orders = wc_get_orders(
array(
'field_query' => array(
'relation' => 'OR',
array(
'field' => 'total',
'value' => 500,
'compare' => '>',
'type' => 'NUMERIC',
),
array(
'field' => 'shipping_total',
'value' => 0,
'compare' => '=',
'type' => 'NUMERIC',
),
),
)
);
date_query, na przykład zamówienia opłacone w ostatnim miesiącu i utworzone przed południem:
$orders = wc_get_orders(
array(
'date_query' => array(
'relation' => 'AND',
array(
'column' => 'date_created_gmt',
'hour' => 12,
'compare' => '<',
),
array(
'column' => 'date_paid_gmt',
'after' => '1 month ago',
),
),
)
);
Dla prostego porównania jednego pola nie używaj field_query. Pola zamówienia są dostępne jako argumenty najwyższego poziomu, na przykład 'billing_city' => 'Kraków'. field_query jest do operatorów i zagnieżdżeń.
Pułapka: to działa tylko na HPOS
Dokumentacja ma przy każdym z tych trzech argumentów tę samą ramkę: obsługa jest dostępna tylko wtedy, gdy HPOS jest skonfigurowanym magazynem zamówień. Konsekwencji nie tłumaczy, więc sprawdziłem w kodzie, co się dzieje na magazynie wpisów.
Dwie rzeczy naraz. Po pierwsze, WC_Order_Data_Store_CPT::query() od wersji 9.2.0 woła wc_doing_it_wrong() z komunikatem "Order query argument (meta_query) is not supported on the current order datastore". Ten notice widać wyłącznie przy włączonym WP_DEBUG. Na produkcji nie zobaczysz nic. Po drugie, niezależnie od notice, metoda budująca argumenty dla WP_Query ma jawny warunek pomijający klucz meta_query. Twój meta_query jest wyrzucany z zapytania, field_query trafia do WP_Query jako nieznany argument i jest ignorowany.
Efekt: snippet "działa", tylko zwraca pełną, nieprzefiltrowaną listę. Kod z sekcji wyżej, który miał znaleźć zamówienia bez faktury, na magazynie wpisów zwróci wszystkie zamówienia ze statusem completed.
To jest lustrzane odbicie problemu z WP_Query. Stare API psuje się na HPOS. Nowe API psuje się na magazynie wpisów. Dlatego istnieje OrderUtil.
OrderUtil: kod, który musi działać w obu magazynach

Kiedy to potrzebne: własna wtyczka dystrybuowana do wielu sklepów, snippet w sklepie, który jeszcze nie przeszedł na HPOS, ale przejdzie, kod raportowy z własnym SQL. Przy samym CRUD (wc_get_order(), get_meta(), save()) sprawdzanie magazynu jest zbędne. Sprawdza się je wtedy, gdy piszesz SQL, używasz meta_query lub field_query, albo rejestrujesz metabox.
Sprawdzenie magazynu:
use Automattic\WooCommerce\Utilities\OrderUtil;
if ( OrderUtil::custom_orders_table_usage_is_enabled() ) {
// Sklep używa HPOS: wp_wc_orders, meta_query i field_query dostępne.
} else {
// Magazyn wpisów: wp_posts i wp_postmeta.
}
Sprawdzenie, czy ID jest zamówieniem. Typowy błąd to 'shop_order' === get_post_type( $id ) w hookach save_post, które na HPOS w ogóle nie odpalają dla zamówień:
use Automattic\WooCommerce\Utilities\OrderUtil;
if ( OrderUtil::is_order( $id, wc_get_order_types() ) ) {
$type = OrderUtil::get_order_type( $id ); // 'shop_order' albo 'shop_order_refund'
}
Metabox na ekranie zamówienia. To najczęstsza przyczyna zgłoszenia "mój metabox zniknął po HPOS": ekran edycji zamówienia nie jest już ekranem posta, więc add_meta_box() z ekranem shop_order nic nie pokazuje.
use Automattic\WooCommerce\Utilities\OrderUtil;
add_action( 'add_meta_boxes', function () {
$screen = OrderUtil::custom_orders_table_usage_is_enabled()
? wc_get_page_screen_id( 'shop-order' )
: 'shop_order';
add_meta_box( 'msm_faktura', 'Faktura', 'msm_render_faktura_metabox', $screen, 'side', 'high' );
} );
function msm_render_faktura_metabox( $post_or_order ) {
$order = ( $post_or_order instanceof WP_Post ) ? wc_get_order( $post_or_order->ID ) : $post_or_order;
if ( ! $order ) {
return;
}
echo esc_html( $order->get_meta( '_numer_faktury' ) );
}
Callback dostaje WP_Post na magazynie wpisów i WC_Order na HPOS. Zamiast rozróżniać w każdej linijce, od razu pobierz obiekt zamówienia i dalej pracuj tylko na nim.
Własny parametr zapytania dla obu magazynów. Ten wzorzec zamyka lukę z meta_query na magazynie wpisów: na HPOS przekładasz swój parametr na meta_query, a na magazynie wpisów na meta_query dla WP_Query wewnątrz WooCommerce. To jest legalne, bo robi to data store, nie Twój kod.
use Automattic\WooCommerce\Utilities\OrderUtil;
// Użycie: wc_get_orders( [ 'numer_faktury' => 'FV/2026/09/0142' ] ).
if ( OrderUtil::custom_orders_table_usage_is_enabled() ) {
add_filter( 'woocommerce_order_query_args', function ( $query_args ) {
if ( ! empty( $query_args['numer_faktury'] ) ) {
$query_args['meta_query'] = $query_args['meta_query'] ?? array();
$query_args['meta_query'][] = array(
'key' => '_numer_faktury',
'value' => $query_args['numer_faktury'],
);
unset( $query_args['numer_faktury'] );
}
return $query_args;
} );
} else {
add_filter( 'woocommerce_order_data_store_cpt_get_orders_query', function ( $query, $query_vars ) {
if ( ! empty( $query_vars['numer_faktury'] ) ) {
$query['meta_query'][] = array(
'key' => '_numer_faktury',
'value' => $query_vars['numer_faktury'],
);
}
return $query;
}, 10, 2 );
}
Jeśli piszesz wtyczkę, zadeklaruj zgodność z HPOS przez FeaturesUtil::declare_compatibility(). Snippet i wyjaśnienie, co ta deklaracja zmienia w panelu, są we wpisie o HPOS, w sekcji o sprawdzaniu gotowości sklepu.
Jak zaudytować i przepisać stare snippety
Krok 1: znajdź podejrzane miejsca. Recipe book podaje wyrażenie regularne do przeszukania kodu; poniżej wersja skrócona do tego, co w praktyce dotyczy zamówień.
grep -rnE 'wpdb|get_post\(|get_post_field|get_post_status|get_post_type|get_posts|get_post_meta|update_post_meta|add_post_meta|delete_post_meta|wp_insert_post|wp_update_post|wp_delete_post|shop_order' \
wp-content/themes/twoj-motyw-child \
wp-content/plugins/twoja-wtyczka
Będzie dużo fałszywych trafień: produkty, strony, kupony. Sprawdzasz tylko te, które dotyczą zamówień.
Krok 2: zamień według tabeli.
| Po staremu | Zgodnie z HPOS |
|---|---|
get_post( $order_id ) |
wc_get_order( $order_id ) |
$order->ID, $post->post_status |
$order->get_id(), $order->get_status() |
get_post_meta( $id, '_k', true ) |
$order->get_meta( '_k' ) |
update_post_meta( $id, '_k', $v ) |
$order->update_meta_data( '_k', $v ); $order->save(); |
delete_post_meta( $id, '_k' ) |
$order->delete_meta_data( '_k' ); $order->save(); |
new WP_Query( [ 'post_type' => 'shop_order' ] ), get_posts() |
wc_get_orders( [ ... ] ) |
'shop_order' === get_post_type( $id ) |
OrderUtil::is_order( $id, wc_get_order_types() ) |
add_action( 'save_post_shop_order', ... ) |
woocommerce_update_order + woocommerce_new_order |
add_meta_box( ..., 'shop_order', ... ) |
add_meta_box( ..., wc_get_page_screen_id( 'shop-order' ), ... ) |
$wpdb->get_results( "... FROM wp_posts WHERE post_type = 'shop_order' ..." ) |
wc_get_orders() z field_query lub meta_query; $wpdb na wp_wc_orders tylko za OrderUtil |
wp_delete_post( $order_id, true ) |
$order->delete( true ) |
Wiersz z hookami wymaga komentarza, bo to drugi po metaboxach powód zgłoszeń "po HPOS przestało działać". woocommerce_update_order( $order_id, $order ) jest wołany w obu data store'ach, więc działa niezależnie od magazynu. Trzy zastrzeżenia. Przy przejściu zamówienia ze statusu roboczego (auto-draft, draft, checkout-draft) na właściwy WooCommerce odpala woocommerce_new_order zamiast woocommerce_update_order, dlatego zamiennikiem save_post_shop_order jest para obu hooków. Przeniesienie do kosza i przywrócenie mają osobne hooki (woocommerce_trash_order, woocommerce_untrash_order). W checkoucie blokowym woocommerce_update_order potrafi odpalić kilka razy dla jednego zamówienia, więc callback musi być idempotentny. Jeśli potrzebujesz "zawsze po zapisie", także bez zmian, jest jeszcze woocommerce_after_order_object_save.
Krok 3: przetestuj w docelowym stanie, czyli na stagingu z włączonym HPOS i wyłączonym trybem zgodności. Po 10.7 to jest stan, do którego sklep i tak zmierza. Jeśli kod idzie do wielu sklepów, zrób drugi przebieg na magazynie wpisów. Po testach zapisu uruchom wp wc hpos verify_data; komendy WP-CLI opisałem we wpisie o HPOS.
Krok 4: dopiero teraz wyłącz tryb zgodności na produkcji, jeśli był włączony jako koło ratunkowe.
Uwaga praktyczna. Gdy snippet siedzi w cudzej wtyczce, nie łataj jej kodu. Łatka znika przy pierwszej aktualizacji. Zgłoś autorowi albo szukaj zamiennika. Jeśli przejmujesz sklep po innym developerze i nie wiesz, co siedzi w functions.php, ten audyt jest pierwszym krokiem, zanim cokolwiek przełączysz; pisałem o tym przy przebudowie sklepu bez utraty SEO i historii zamówień.
Kiedy NIE
Nie przepisuj kodu, który operuje na produktach, kuponach i stronach. HPOS dotyczy zamówień i zwrotów. WP_Query i get_post_meta() na produkcie są nadal poprawne. Częsty błąd nadgorliwości to "naprawianie" get_post_meta() w kodzie produktów, które przez to przestaje działać.
Nie przepisuj SQL do tabel pozycji zamówienia. wp_woocommerce_order_items i wp_woocommerce_order_itemmeta nie zmieniły się i są wspólne dla obu magazynów.
Nie zakładaj, że "zawsze CRUD" znaczy "zawsze najszybciej". Raport na setkach tysięcy zamówień przez wc_get_orders() z pełnymi obiektami będzie wolny. Tam lepiej sprawdzają się ID i partie, świadomy SQL na wp_wc_orders za OrderUtil albo WooCommerce Analytics i tabele lookup. Jeśli baza jest wąskim gardłem całego sklepu, to osobny temat, opisany we wpisie o wolnym sklepie WooCommerce.
Nie dokładaj OrderUtil i podwójnych ścieżek do kodu, który ma działać w jednym sklepie z HPOS na stałe i bez trybu zgodności. Wystarczy CRUD.
Nie używaj meta_query ani field_query w kodzie, który może trafić na magazyn wpisów, na przykład w dystrybuowanej wtyczce. Zamiast tego własny parametr przez dwa filtry, jak w sekcji o OrderUtil.
I nie rób audytu "na sucho". Sklep z włączonym trybem zgodności, w którym wszystko "działa", nie jest dowodem na nic. Po 10.7 rozjazd danych jest cichy. Audyt regexem i verify_data zamiast "u mnie działa".
Powiązane wpisy z serii
- HPOS w WooCommerce: co to jest, czy warto włączyć i jak to zrobić bez utraty zamówień
- Wolny sklep WooCommerce: najczęstsze przyczyny
- Przebudowa sklepu WooCommerce bez utraty SEO i historii zamówień
Jeśli nie chcesz sam przechodzić przez audyt własnego kodu i listę wtyczek, umów bezpłatną konsultację.
FAQ
Tak, na obu magazynach. Różnica dotyczy tylko argumentów `meta_query`, `field_query` i `date_query`, które działają wyłącznie na HPOS. Na magazynie wpisów są po cichu usuwane z zapytania, a jedyny ślad to notice `doing_it_wrong` przy włączonym `WP_DEBUG`.
`wc_get_orders()` to skrót do `WC_Order_Query::get_orders()`. Przyjmują te same argumenty. Klasa jest wygodniejsza, gdy budujesz zapytanie krokami przez `set()`.
Przez własny parametr zapytania obsłużony filtrem `woocommerce_order_data_store_cpt_get_orders_query`, który przekłada go na `meta_query` dla `WP_Query` wewnątrz WooCommerce. Snippet jest w sekcji o `OrderUtil`.
Bo na HPOS meta zamówień leżą w `wp_wc_orders_meta`, a `get_post_meta()` czyta `wp_postmeta`. Użyj `wc_get_order( $id )->get_meta( '_klucz' )`.
Zapisuje do `wp_postmeta`, ale od WooCommerce 10.7 ta zmiana nie wraca do tabel HPOS, bo sync on read jest wyłączony. Sklep czyta z HPOS, więc zapis jest niewidoczny. Szczegóły we wpisie o HPOS.
`Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled()`.
`wc_get_orders()` nie ma takiego parametru. Zawęź zapytanie datami i przejdź po `get_items()`, albo dodaj własny parametr przez filtry. Tabele pozycji zamówienia są wspólne dla obu magazynów, więc własny SQL z `prepare()` też jest tam poprawny.
Bo zamówienie nie jest już postem. Zamiennikiem jest para `woocommerce_update_order` i `woocommerce_new_order`, które odpalają w obu magazynach.
Tyle, ile wynosi `posts_per_page` w ustawieniach czytania, zwykle 10. Wartość `-1` zwraca wszystkie, co przy dużym sklepie i pełnych obiektach zjada pamięć; wtedy `'return' => 'ids'` i partie.