Мета
Пояснювати, що таке HPOS, навіщо він потрібен, і писати код, сумісний з ним.
Ключові поняття
- HPOS (High-Performance Order Storage) — замовлення в окремих таблицях замість
wp_posts - За замовчуванням на нових сайтах з WooCommerce 8.2; старі магазини переходять вручну
- Режим синхронізації (compatibility mode): дані пишуться в обидва сховища на час переходу
- Оголошення сумісності плагіна:
FeaturesUtil::declare_compatibility( 'custom_order_tables', ... ) OrderUtil::custom_orders_table_usage_is_enabled()— перевірка, яке сховище активне- Екран замовлень змінюється:
admin.php?page=wc-ordersзамістьedit.php?post_type=shop_order
Схема
flowchart TB
A["Старий магазин<br/>wp_posts"] --> B["Увімкнути синхронізацію"]
B --> C["Фонова міграція<br/>wp wc hpos sync"]
C --> D["Перевірка<br/>wp wc hpos verify_cot_data"]
D --> E["HPOS як основне сховище"]
E --> F["Вимкнути синхронізацію<br/>після тестів"]
Код
Оголошення сумісності в головному файлі плагіна:
<?php
add_action( 'before_woocommerce_init', static function () {
if ( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class ) ) {
\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility(
'custom_order_tables',
__FILE__,
true
);
}
} );
Колонка в списку замовлень для обох екранів:
<?php
use Automattic\WooCommerce\Utilities\OrderUtil;
$screen = OrderUtil::custom_orders_table_usage_is_enabled()
? 'woocommerce_page_wc-orders'
: 'edit-shop_order';
add_filter( "manage_{$screen}_columns", static function ( array $columns ): array {
$columns['erp_id'] = __( 'ERP ID', 'my-plugin' );
return $columns;
} );
// HPOS передає об'єкт замовлення, старий екран — ID поста.
add_action( 'manage_woocommerce_page_wc-orders_custom_column', 'my_render_erp_column', 10, 2 );
add_action( 'manage_shop_order_posts_custom_column', 'my_render_erp_column', 10, 2 );
function my_render_erp_column( string $column, $order_or_id ): void {
if ( 'erp_id' !== $column ) {
return;
}
$order = $order_or_id instanceof WC_Order ? $order_or_id : wc_get_order( $order_or_id );
echo esc_html( $order ? $order->get_meta( '_erp_id' ) : '' );
}
Типові помилки
| Симптом | Причина | Виправлення |
|---|---|---|
| Плагін позначено як несумісний у WooCommerce → Settings → Advanced → Features | Немає declare_compatibility | Оголосити сумісність після перевірки коду |
| Колонка зникла після ввімкнення HPOS | Хуки лише для edit-shop_order | Підключити хуки обох екранів |
| SQL-звіт показує нулі | Прямий запит до wp_posts з post_type = shop_order | wc_get_orders() або запит до HPOS-таблиць з перевіркою режиму |
Слабка і сильна відповідь
Питання: Що потрібно зробити, щоб плагін підтримував HPOS?
Слабка відповідь. Додати
declare_compatibilityв плагін.
Сильна відповідь. Спершу прибрати прямий доступ до замовлень:
get_post_meta,WP_Queryпоshop_order, SQL доwp_posts. Замінити наwc_get_order(),wc_get_orders()і CRUD-мету. Адаптувати хуки адмін-екрана. Перевірити з HPOS і без нього, і лише тоді оголосити сумісність.
Чому друга сильніша: Оголошення — це наслідок перевірки, а не сама сумісність. Кандидат знає, що саме ламається.
Практичне завдання
Візьміть будь-який свій плагін, що працює із замовленнями. Знайдіть get_post_meta, update_post_meta, WP_Query і SQL із shop_order. Перепишіть на CRUD, додайте declare_compatibility і перевірте в обох режимах. Команди міграції — у терміналі.
Питання з інтерв'ю
Замовлення мають власні таблиці з потрібними колонками й індексами (статус, дата, клієнт, сума). Немає тисяч рядків у wp_postmeta на кожне замовлення і важких JOIN. Пошук і звіти по замовленнях не конкурують з постами і сторінками.
Під час переходу WooCommerce пише замовлення в обидва сховища. Можна повернутися назад, а старі плагіни, які читають wp_posts, ще отримують дані. Після переходу синхронізацію вимикають, бо вона подвоює запис.
\Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled().