29 августа 2023

Гайд по WooCommerce High-Performance Order Storage

6 минут
Гайд по WooCommerce High-Performance Order Storage

В данной статье хотелось бы затронуть тему новой фичи WooCommerce High-Performance Order Storage (в дальнейшем HPOS) которая по заверениям разработчиков должна сделать работу с базой данных более надежной, а саму систему электронной коммерции более быстрой.

Установка и настройка

Чтобы установить  HPOS, нужно зайти в панели администрирования WordPress — WooCommerce → Settings → Advanced → Features

Опция High performance order storage

Так же HPOS можно включить, используя WP CLI для этого используйте данную команду:

wp option set woocommerce_feature_custom_order_tables_enabled yes

После включения HPOS будут созданы новые таблицы для новых WooCommerce заказов, также на странице настроек можно включить синхронизацию уже существующих заказов, в таком случае они будут перенесены из таблицы wp_posts в новые таблицы

Если на сайте активированы плагины которые не поддерживают HPOS, то страница включения фичи будет выглядеть так:

Для того, чтобы разблокировать HPOS нужно деактивировать несовместимые плагины или добавить поддержку HPOS в них.

Официальную страницу с описанием и инструкциями по работе с новой фичей можно найти тут

Поддержка плагинов

Если вы разработчик плагинов под WooCommerce, то на текущий момент поддержка HPOS не обязательна (если вы готовы к тому, что ваш плагин не будет работать на некоторых сайтах), но думаю что в обозримом будущем поддержка HPOS будет обязательно для всех WooCommerce плагинов.

Вот код, который разработчики WooCommerce предоставляют чтобы добавить в ваш плагин интеграцию с HPOS:

add_action( 'before_woocommerce_init', function() {
	if ( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class ) ) {
		\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true ); //__FILE__ должен вести в основному файлу вашего плагина
	}
} );

Также разработчики WooCommerce предоставляют код который нужно добавить в ваш плагин в случае если он не поддерживает HPOS:

add_action( 'before_woocommerce_init', function() {
	if ( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class ) ) {
		\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, false );
	}
} );

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

Чтобы определить включена ли на сайте фича HPOS используется метод

OrderUtil::custom_orders_table_usage_is_enabled()

Он возвращает true или false, ее можно использовать для обратной совместимости ваших плагинов, например, если вы делаете напрямую запросы к базе данных, чтобы получать заказы.

Чтобы получить объект заказа больше нельзя использовать метод get_post( $post_id ), так как данный метод производит поиск по таблице wp_posts которую со включением HPOS WooCommerce перестает использовать для хранения заказов, вместо этого используйте WooCommerce  метод  wc_get_order( $post_id ) для получения заказа, на стороне WooCommerce уже предусмотрен поиск по новой таблице.

То же самое касается и мета полей для заказов, вместо методов:

update_post_meta( $post_id, $meta_key_1, $meta_value_1 );
add_post_meta( $post_id, $meta_key_2, $meta_value_2 );
delete_post_meta( $post_id, $meta_key_3, $meta_value_3 );

Теперь обязательно использовать методы:

$order = wc_get_order( $post_id );
$order->update_meta_data( $meta_key_1, $meta_value_1 );
$order->add_meta_data( $meta_key_2, $meta_value_2 );
$order->delete_meta_data( $meta_key_3, $meta_value_3 );
$order->save();

В данных примерах нет ничего принципиально нового, все используемые методы были и раньше просто включение HPOS больше не позволяет использовать функции WordPress для работы с заказами, а обязывает использовать аналогичные функции WooCommerce.

Далее рассмотрим пример получения типа заказа и проверки является ли данный post_id заказом, если раньше код выглядел так:

// Pattern to check when an ID is an order
'shop_order' === get_post_type( $post_id ); // or
in_array( get_post_type( $post_type ), wc_get_order_types() );

То сейчас необходимо использовать класс OrderUtil:

use Automattic\WooCommerce\Utilities\OrderUtil;
'shop_order' === OrderUtil::get_order_type( $post_id ); 
// or
OrderUtil::is_order( $post_id, wc_get_order_types() );

Для работы с метабоксами заказов также нужно предусмотреть наличие отдельных таблиц для метаполей, ниже представлен вариант добавления метабокса учитывая наличие HPOS:

use Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController;

add_action( 'add_meta_boxes', 'add_xyz_metabox' );

function add_xyz_metabox() {
	$screen = wc_get_container()->get( CustomOrdersTableController::class )->custom_orders_table_usage_is_enabled()
		? wc_get_page_screen_id( 'shop-order' )
		: 'shop_order';

	add_meta_box(
		'xyz',
		'Custom Meta Box',
		'render_xyz_metabox',
		$screen,
		'side',
		'high'
	);
}
function render_xyz_metabox( $post_or_order_object ) {
    $order = ( $post_or_order_object instanceof WP_Post ) ? wc_get_order( $post_or_order_object->ID ) : $post_or_order_object;
    
    // ... rest of the code. $post_or_order_object should not be used directly below this point.
}

Как видите необходимы дополнительные проверки — включена ли фича HPOS и является ли объект заказа экземпляром WP_Post.

Помимо примеров кода разработчиками WooCommerce было представлено два набора регулярных выражений для аудита кодовой базы. Для аудита запросов к базе для получения заказов:

wpdb|get_post|get_post_field|get_post_status|get_post_type|get_post_type_object|get_posts|metadata_exists|get_post_meta|get_metadata|get_metadata_raw|get_metadata_default|get_metadata_by_mid|wp_insert_post|add_metadata|add_post_meta|wp_update_post|update_post_meta|update_metadata|update_metadata_by_mid|delete_metadata|delete_post_meta|delete_metadata_by_mid|delete_post_meta_by_key|wp_delete_post|wp_trash_post|wp_untrash_post|wp_transition_post_status|clean_post_cache|update_post_caches|update_postmeta_cache|post_exists|wp_count_post|shop_order

Для аудита страниц в панели администрирования сайта:

post_updated_messages|do_meta_boxes|enter_title_here|edit_form_before_permalink|edit_form_after_title|edit_form_after_editor|submitpage_box|submitpost_box|edit_form_advanced|dbx_post_sidebar|manage_shop_order_posts_columns|manage_shop_order_posts_custom_column

Используйте данные выражения, чтобы найти в вашем коде то что нужно заменить для поддержки HPOS.

Так же изменения затронули и WC Query API, с заметками касаемо этих изменений вы можете ознакомиться тут.

Разработчики WooCommerce также предусмотрели возможность отката версии в случае если HPOS вам не подошел или ваши плагины не поддерживают его, о возможности отката можно почитать тут.

В общих словах интеграция с новой фичей не выглядит чем-то принципиально новым. Разработчики WooCommerce вынуждают разработчиков плагинов использовать вместо WordPress методов свои, для тех разработчиков кто и раньше предпочитал пользоваться WooCommerce методами везде, где это было возможно, интеграция практически ничего не требует. Для тех же, кто пользовался в основном функциональностью WordPress придется провести небольшой объем работ над своими плагинами для добавления поддержки HPOS и по моему мнению оно того стоит.

Преимущества

По заверениям разработчиков основные преимущества WooCommerce HPOS это — Масштабируемость, Надежность и Простота. Мы разберем каждый из этих пунктов и расскажем вам свое мнение.

  1. Масштабируемость – говоря масштабируемость разработчики WooCommerce подразумевают увеличение количества клиентов в магазине и как следствие увеличение нагрузки на базу.
    Если раньше все посты WordPress будь-то посты блога, страницы магазина или заказы хранились в одной таблице _posts, то HPOS переносит заказы и их мета поля в отдельную таблицу что дает возможность настроить индексы в новых таблицах (что они и делают), что в свою очередь позволяет значительно снизить нагрузку на базу и ускорить работу с заказами в целом – это можно однозначно выделить как жирный плюс в работе с WooCommerce
  2. Надежность – в данном случае подразумевается что возможность делать бекапы для заказов стало проще и удобнее за счет хранения в отдельных таблицах, на мой взгляд это не выглядит как большой плюс, а скорее просто структура базы становиться удобнее и лаконичнее.
  3. Простота – заключается в том, что работа напрямую с таблицами стала удобнее и приятнее, искать\менять\просматривать данные напрямую в базе не пролистывая тонны записей которые не относятся к заказами, чтобы найти тот самый заказ стало действительно проще. Также в данную таблицу при желании можно добавить дополнительные поля и индексы, что делает работу с заказами в WooCommerce более гибкой и это определенно плюс фичи HPOS.

В итоге разработчики WooCommerce сделали довольно простую фичу которая давно напрашивалась, но при этом прилично улучшает работу WooCommerce

Заключение

Можно сказать, что новая фича от WooCommerce действительно стоит того, чтобы её внедрить. Да это дополнительная головная боль для разработчиков, да далеко не всем это нужно, но если вы разрабатываете плагины для широкой аудитории или владеете WooCommerce магазином с большой загрузкой, то HPOS для вас.

Лично мне импонирует в каком направлении развивается WooCommerce система, думаю что в зависимости от результатов внедрения HPOS (уверен они собирают статистику) будет как минимум принудительный переход на HPOS и в дальнейшем перенос в отдельную таблицу уже товаров.

Так что если вы разрабатываете плагины для широкой аудитории не забывайте добавлять поддержку HPOS для новых плагинов и обновлять кодовую базу для уже выпущенных.