Урок 1.3. HPOS

Мета

Пояснювати, що таке 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

Схема

MERMAID
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
<?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
<?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_orderwc_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 — Модуль 1. WooCommerce як система

Питання з інтерв'ю

Замовлення мають власні таблиці з потрібними колонками й індексами (статус, дата, клієнт, сума). Немає тисяч рядків у wp_postmeta на кожне замовлення і важких JOIN. Пошук і звіти по замовленнях не конкурують з постами і сторінками.

Під час переходу WooCommerce пише замовлення в обидва сховища. Можна повернутися назад, а старі плагіни, які читають wp_posts, ще отримують дані. Після переходу синхронізацію вимикають, бо вона подвоює запис.

\Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled().

Save your progress

Sign in or create a free account to mark lessons as completed and continue the whole course. You will come back to this lesson.