WooCommerce / HPOS
HPOS en WooCommerce: problemas habituales con código personalizado
Respuesta corta
Con HPOS como almacenamiento principal, los pedidos viven en wp_wc_orders y sus tablas relacionadas, no en wp_posts y wp_postmeta. El código que lee o escribe pedidos con funciones de entradas, WP_Query o SQL sobre las tablas de entradas deja de funcionar, a menudo en silencio y devolviendo valores vacíos. Reescríbelo con la API de pedidos (wc_get_order(), wc_get_orders(), $order->get_meta(), $order->update_meta_data() más $order->save()), actualiza los hooks de administración para la nueva pantalla de pedidos y declara la compatibilidad con HPOS en tus plugins.
Síntomas
- Los meta de pedido que lee el código a medida llegan vacíos tras activar HPOS.
- Faltan columnas, filtros o cajas meta personalizados en la nueva pantalla de pedidos.
- Las exportaciones, los informes o las integraciones dejan de incluir los pedidos nuevos.
- Los valores que guarda el código a medida no aparecen en el pedido, o desaparecen con el siguiente guardado.
- WooCommerce avisa de que hay plugins activos incompatibles y no te deja cambiar a HPOS.
Causas más comunes
| Patrón | Por qué falla |
|---|---|
get_post_meta( $order_id, '_my_key', true ) |
Lee wp_postmeta, que no es la fuente de verdad con HPOS |
update_post_meta( $order_id, … ) |
Escribe en el almacenamiento de entradas; HPOS no lo ve, o la sincronización lo sobrescribe |
new WP_Query( [ 'post_type' => 'shop_order' ] ) / get_posts() |
Consulta wp_posts, donde puede que los pedidos nuevos no existan |
Consultas $wpdb sobre wp_posts / wp_postmeta para pedidos |
Esquema antiguo escrito a mano |
wp_insert_post() / wp_update_post() sobre pedidos |
Se salta los almacenes de datos de pedidos |
Solo manage_edit-shop_order_columns |
Hooks de la pantalla antigua; la pantalla de HPOS usa otros |
add_meta_box( …, 'shop_order' ) |
ID de pantalla incorrecto para la pantalla de edición de HPOS |
Diagnóstico
1. Comprueba qué almacenamiento es el principal
WooCommerce → Ajustes → Avanzado → Características muestra si los pedidos se guardan en las tablas de HPOS o en las antiguas tablas de entradas, y si el modo de compatibilidad mantiene ambos sincronizados. Mientras la sincronización está activa, el código antiguo puede parecer que funciona al leer, lo que oculta el problema hasta que se desactiva.
2. Busca en el código
Busca en el tema, los plugins a medida, los mu-plugins y los plugins de snippets:
$ grep -rnE "get_post_meta|update_post_meta|delete_post_meta|wp_insert_post|wp_update_post" wp-content/themes/my-theme wp-content/plugins/my-plugin
$ grep -rnE "shop_order|wp_posts|wp_postmeta|post_type *=" wp-content/themes/my-theme wp-content/plugins/my-pluginCada resultado requiere una decisión: ¿toca pedidos? El código de productos y páginas no se ve afectado.
3. Revisa las extensiones
WooCommerce lista los plugins incompatibles en la pantalla de Características. Para cada uno, comprueba si alguna actualización declara la compatibilidad; si no, pregunta al desarrollador o planifica un sustituto.
4. Prueba en staging con la sincronización activada y después desactivada
Activa HPOS en staging con el modo de compatibilidad, recorre los flujos críticos (checkout, notificaciones de pago, emails, ediciones en la administración, exportaciones, integraciones) y después desactiva la sincronización y vuelve a recorrerlos. El código que solo funciona con la sincronización activada no es compatible.
Registros y comprobaciones técnicas
- La pantalla de Características: almacenamiento principal, estado de la sincronización, plugins incompatibles.
- WooCommerce → Estado → Registros:
fatal-errorstras cambiar de almacenamiento. - Notas y meta de pedidos de prueba, comparados antes y después del cambio.
- Comparaciones de solo lectura del mismo pedido en ambos almacenamientos mientras la sincronización está activa.
Soluciones
Lee y escribe pedidos con la API de pedidos
// Leer
$order = wc_get_order( $order_id );
if ( ! $order ) {
return;
}
$po_number = $order->get_meta( '_po_number' );
// Escribir: los cambios no se guardan hasta llamar a save()
$order->update_meta_data( '_po_number', sanitize_text_field( $value ) );
$order->save();
// Consultar
$orders = wc_get_orders( [
'status' => [ 'wc-processing' ],
'limit' => 50,
'meta_query' => [
[ 'key' => '_po_number', 'compare' => 'EXISTS' ],
],
] );Da soporte a las dos pantallas de administración
use Automattic\WooCommerce\Utilities\OrderUtil;
// Columnas: pantalla antigua y pantalla de HPOS
add_filter( 'manage_edit-shop_order_columns', 'myplugin_add_column' );
add_filter( 'manage_woocommerce_page_wc-orders_columns', 'myplugin_add_column' );
add_action( 'manage_shop_order_posts_custom_column', function ( $column, $post_id ) {
myplugin_render_column( $column, wc_get_order( $post_id ) );
}, 10, 2 );
add_action( 'manage_woocommerce_page_wc-orders_custom_column', function ( $column, $order ) {
myplugin_render_column( $column, $order );
}, 10, 2 );
// Caja meta en la pantalla de edición de pedidos que esté activa
add_action( 'add_meta_boxes', function () {
add_meta_box( 'myplugin-box', 'Orden de compra', 'myplugin_render_box', wc_get_page_screen_id( 'shop-order' ), 'side' );
} );
function myplugin_render_box( $post_or_order ) {
$order = $post_or_order instanceof WP_Post ? wc_get_order( $post_or_order->ID ) : $post_or_order;
// …
}Declara la compatibilidad en tus propios plugins
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 );
}
} );Qué no hacer
- No declares la compatibilidad para quitar el aviso antes de revisar el código.
- No desactives el modo de compatibilidad nada más cambiar: mantenlo como camino de vuelta atrás hasta que la tienda lleve un tiempo funcionando bien.
- No «arregles» los valores que faltan copiando meta entre tablas con SQL.
Cuándo recurrir a un experto
Recurre a un ingeniero cuando la auditoría encuentra accesos a pedidos repartidos por muchos archivos, cuando una extensión imprescindible no tiene versión compatible, cuando los datos de pedidos ya difieren entre almacenamientos, o cuando la tienda es tan grande que la propia migración necesita planificación.
Problemas relacionados
- WooCommerce / Pedidos Pedidos de WooCommerce que no aparecen o son incorrectos Antes de dar un pedido por perdido, revisa todos los estados, los borradores y el proveedor de pagos. Los totales incorrectos suelen venir de impuestos, cargos, cupones o recálculos.
- WooCommerce / Errores Error fatal en WooCommerce: guía práctica para resolverlo Lee bien el error fatal (archivo, línea, traza) y relaciónalo con el cambio que lo provocó.
- WooCommerce / Errores Conflicto de plugins en WooCommerce: cómo encontrar la causa Parte de las evidencias (el error, el momento, la petición) y aísla en staging por mitades, no plugin a plugin en producción.
Preguntas frecuentes
¿Cómo sé si mi código es compatible con HPOS?
Busca accesos directos a pedidos: get_post_meta y update_post_meta sobre IDs de pedido, WP_Query o get_posts con shop_order, wp_insert_post para pedidos y SQL contra wp_posts o wp_postmeta para pedidos. El código que solo usa wc_get_order, wc_get_orders y los métodos del objeto pedido suele ser compatible.
¿Por qué desaparece mi columna personalizada de la lista de pedidos?
La pantalla de pedidos de HPOS es otra página de administración con otros hooks. Las columnas registradas con manage_edit-shop_order_columns necesitan también sus equivalentes manage_woocommerce_page_wc-orders_columns.
¿Tengo que declarar la compatibilidad?
Sí, en tus propios plugins. WooCommerce usa esa declaración para decidir si se puede activar HPOS. Decláralo solo después de revisar el código.
¿Puedo seguir ejecutando SQL sobre los pedidos?
Mejor usa wc_get_orders(). Si de verdad necesitas SQL, obtén los nombres de tabla de WooCommerce en lugar de escribir wp_posts a mano, y recuerda que el esquema es distinto en cada almacenamiento.