Actualizar atributos personalizados de WooCommerce programáticamente

17 nov 2015, 11:54:55
Vistas: 18.8K
Votos: 2

Primero que nada, gracias por ser parte de una comunidad impresionante que me ha ayudado miles de veces antes.

En mi entorno de Wordpress (tema Enfold, plugin Woocommerce) creé un sistema para usar una encuesta como entrada para publicaciones creadas al instante en un sitio front-end. Las respuestas de la encuesta se incluyen en publicaciones generadas automáticamente (tipo 'producto') incluyendo Atributos Personalizados de WooCommerce.

Escribí consultas personalizadas que responden a disparadores en mySQL - insertando y actualizando wp_posts, wp_terms, wp_postmeta, wp_term_relationships.

Todo funciona bien, excepto por una cosa: los atributos personalizados de producto de WooCommerce no se muestran instantáneamente en los filtros desplegables/select del sitio web. Sin embargo, presionar 'manualmente' el botón Actualizar en la página de Wordpress hace el trabajo.

Estoy buscando una manera de replicar exactamente el presionar 'manualmente' Actualizar en el CMS de Wordpress. Hasta ahora, la publicación misma se carga exitosamente en el sitio web, pero sus atributos de producto WooCommerce no se inicializan.

Hasta ahora, he intentado muchas soluciones alternativas:

Aún así, todos los intentos solo actualizan las publicaciones en wp_posts, aparentemente no las relaciones/atributos personalizados de producto subyacentes.

Mi única solicitud sería replicar programáticamente el hacer clic en 'Actualizar' en el entorno CMS de Wordpress. Esto me ayudaría a automatizar el proceso en lugar de intervenir manualmente.

¿Podrías por favor sugerirme una manera de hacer eso?

Muchas gracias por tu tiempo!

ACTUALIZACIÓN:

Hola Tom,

Después de profundizar en tu respuesta, todavía no entiendo.

Mis consultas actualizan/insertan todas las tablas necesarias. Prácticamente siguen todos los pasos de los scripts php a los que te refieres.

Cuando reviso un producto en el CMS, veo todos los datos - y especialmente los atributos - cargados correctamente. Cuando presiono Actualizar manualmente en el CMS y comparo los datos en las tablas mySQL antes y después de actualizar, no veo diferencias significativas. Lo único que veo es el valor para _product_attributes en wp_postmeta que es ligeramente diferente (cadena serializada).

Sin embargo, cuando experimento con este valor (vaciar/cambiarlo para la publicación específica en wp_postmeta), nada cambia en los atributos - y todo sigue funcionando al filtrar.

Lo que me lleva a las preguntas:

  • ¿Qué sucede exactamente al presionar 'Actualizar' manualmente?
  • ¿Hay otro almacenamiento además de las tablas mySQL en el que algunas partes estén conectadas de alguna manera?
  • ¿Sería posible para mí 1) tomar el procedimiento 'crear producto' al que te refieres como garantizado y omitirlo (ya que ejecuté mis propias consultas) y luego 2) solo llamar al procedimiento exacto que se ejecuta al presionar Actualizar - para que 'ata' todo sin recrear todas las entradas de la base de datos?
  • Si es así, ¿dónde encontraría este procedimiento específico?

Tu ayuda es muy apreciada. ¡Gracias! Thom

2
Comentarios

¿Estás agregando productos a la base de datos mediante tus "disparadores personalizados" o los triggers de MySQL están respondiendo cuando insertas datos en la base de datos a través de WordPress? ¿O estás insertando manualmente datos de WordPress (¿productos?) en la base de datos y aparecen en el administrador? Si puedes aclararme un poco, creo que puedo ayudarte.

Tom Tom
17 nov 2015 13:08:38

Gracias por tu rápida respuesta, Tom. Funciona de la siguiente manera: - El usuario completa una encuesta en la tabla wp_fsq_data - El trigger notifica la inserción en esta tabla de encuestas y ejecuta la consulta 1: leyendo una cadena serializada en una tabla 'conv1' - El trigger notifica la inserción en esta tabla conv1 y ejecuta la consulta 2: etiquetando valores numéricos como cadenas en una tabla temporal 'conv2' - El trigger notifica la inserción en esta tabla conv2 y ejecuta la consulta 3: insertando/actualizando todos los datos en la estructura de WP (wp_posts, wp_terms, wp_postmeta, wp_relationships) - La publicación aparece en el front-end sin atributos en los menús desplegables/selectores.

Thom Rommens Thom Rommens
17 nov 2015 13:30:44
Todas las respuestas a la pregunta 3
1

OK, yo tuve una variación de este mismo problema y te guiaré a través de él.

Todo funciona bien, excepto por una cosa: Los atributos personalizados de productos en WooCommerce no se muestran instantáneamente en los filtros desplegables/select en el sitio web. Sin embargo, al presionar 'manualmente' Actualizar en la página de WordPress se soluciona.

Al mostrar los atributos, WooCommerce utiliza esta función: wc_get_attribute_taxonomies() (http://woocommerce.wp-a2z.org/oik_api/wc_get_attribute_taxonomies/)

Notarás que en esa función obtiene los datos de un 'transient' (piensa en datos cacheados, ver http://codex.wordpress.org/Transients_API).

Si estás subiendo datos manualmente a la base de datos, es probable que hayas omitido subir el transient (que va en wp_options por cierto). Al presionar actualizar en el panel de administración de WordPress ejecutas la función que actualiza el transient, por eso funcionan/muestran entonces y no antes.

Para que esto funcione, debes asegurarte de que tu actualización manual de MySQL también actualice el transient. En mi caso, al agregar manualmente atributos de productos en WooCommerce, tuve que agregar una fila en wp_options con options_name _transient_wc_attribute_taxonomies y mis atributos en el array serializado en la columna option_value (más un ID con autoload configurado en yes). Pero hay otros transients, así que depende de qué función está causando el problema y qué estás intentando mostrar. Puedes ver cuál te falta haciendo una búsqueda en MySQL por %transient% en wp_options una vez antes de hacer clic en actualizar en el panel de administración de WordPress y una vez después, luego comparando los datos.

1 abr 2016 18:29:15
Comentarios

¡Los transitorios son exactamente el problema y por qué no se actualizan en el front-end. ¡Malditos transitorios!

Solomon Closson Solomon Closson
9 sept 2016 18:28:34
2

¿Estás actualizando también los términos dentro del producto de Woocommerce? Tanto Wp_term_taxonomy como wp_woocommerce_attribute_taxonomies necesitan ser actualizados con tus términos de taxonomía para permitir que el producto de Woocommerce muestre los desplegables de variaciones como "Color" o "Tamaño".

Al crear un producto de Woocommerce mediante programación, las Variaciones de Producto necesitan ser insertadas y vinculadas a atributos existentes (taxonomías creadas dentro de Woocommerce).

Revisa el meta key del post "_product_attributes" que contiene los datos de los atributos. Todavía necesitarás asociar los términos (atributos) con tu producto (dentro de wp_term_taxonomy) pero espero que esto te dé una dirección para avanzar.

También revisa las funciones create_product (https://github.com/woothemes/woocommerce/blob/master/includes/api/class-wc-api-products.php#L237) y save_variations (https://github.com/woothemes/woocommerce/blob/master/includes/api/class-wc-api-products.php#L1692) que describen cómo realizar la creación del producto y sus variaciones.

17 nov 2015 13:46:42
Comentarios

Gracias de nuevo, Tom. Sí, olvidé mencionar wp_term_taxonomy. Sí, también estoy insertando/actualizando esa tabla.

Como el conjunto de atributos no cambia y no hay un conteo registrado en wp_woocommerce_attribute_taxonomies, ¿qué es exactamente lo que necesita actualizarse ahí?

Gracias por esos enlaces. ¡Los revisaré y te haré saber!

Saludos, Thom

Thom Rommens Thom Rommens
17 nov 2015 15:02:01

Thom, ¿te funcionó esto?

Tom Tom
18 oct 2017 15:35:46
0
-1

Esta es una opción con código PHP:


function change_price_by_type( $product_id, $price, $price_type) {
   update_post_meta( $product_id, '_' . $price_type, $price );
}

function change_price_all_types( $product_id, $price ) {
    change_price_by_type( $product_id, $price, 'price' );
    change_price_by_type( $product_id, $price, 'sale_price' );
    change_price_by_type( $product_id, $price, 'regular_price');
}


function change_product_price( $product_id, $price ) {
    change_price_all_types( $product_id, $price ); 
    $product = wc_get_product( $product_id ); // Manejo de productos variables

    if ( $product->is_type( 'variable' ) ) {
        // RM: Obtener variaciones que también están agotadas
        $args = array(
        'post_type'     => 'product_variation',
        'post_status'   => array( 'private', 'publish' ),
        'numberposts'   => -1,
        'orderby'       => 'menu_order',
        'order'         => 'asc',
        'post_parent'   => $product_id // $post->ID 
        );
        $variations = get_posts( $args ); 
        foreach ( $variations as $variation ) {
                change_price_all_types( $variation->ID, $price );
        }
    }
}

$args     = array( 'post_type' => 'product', 'posts_per_page' => 3000);
$products = get_posts( $args ); 

foreach($products as $product) {
    change_product_price($product->ID, 9.99);
    echo $product->ID;
}

exit;

Luego ve a phpMyAdmin y ejecuta las siguientes consultas SQL (puede que necesites cambiar el nombre de tu tabla en lugar de wp_).


UPDATE `wp_postmeta`
SET `meta_value` = ''
WHERE `meta_key` IN ('_sale_price', '_sale_price_dates_from', '_sale_price_dates_to')
  AND `post_id` IN
    (SELECT `ID`
     FROM `wp_posts`
     WHERE `post_type` = 'product'
       AND `post_status` = 'publish' );

Limpiar caché:


DELETE
FROM `wp_options`
WHERE (`option_name` LIKE '_transient_wc_var_prices_%'
    OR `option_name` LIKE '_transient_timeout_wc_var_prices_%')

El código SQL fue tomado de: http://www.technoedu.com/forums/topic/wordpress-solved-copy-woocommerce-products-sale-prices-to-regular-prices-and-reset-sale-prices/

12 sept 2017 16:10:03