WooCommerce agrega campos de productos según la cantidad

6 minutos de lectura

Buenos días.

¿Hay alguna manera de agregar campos de entrada a un producto en WooCommerce de forma dinámica en función de la cantidad de productos seleccionados?

He encontrado muchas soluciones en las que puede haber campos estáticos, pero ninguna en la que se actualice automáticamente. Por ejemplo, si tengo 3 cantidad en la página del producto, para agregar un nombre, número de celular y dirección de correo electrónico para cada producto y es un campo obligatorio.

Las opciones que he visto son:

https://wordpress.org/plugins/woo-checkout-field-editor-pro/

https://wordpress.org/plugins/wc-fields-factory/

Supongamos que tiene un sistema de reservas en su tienda WooCommerce y desea capturar la información adicional al finalizar la compra si alguien reserva más de una cantidad. Por ejemplo, si tiene un sitio de eventos/talleres y desea capturar el nombre, el correo electrónico, el teléfono y la dirección de todos los que asistieron a su evento/taller y alguien reserva 3 cantidades en su sitio web, entonces necesita campos personalizados dinámicos adicionales para capturar los detalles. de otros 2 asistentes. Entonces, si alguien agrega 3 cantidades al carrito, la página de pago agrega campos adicionales para otros 2 asistentes, si se agregan 4 cantidades al carrito, agrega campos para otros 3 asistentes.

Dentro de la siguiente función, verificaremos cuántas cantidades tiene el usuario en su carrito y agregaremos los campos adicionales a la página de pago si la cantidad es más de 1. Y guardaremos los valores de los campos para mostrarlos en el pedido en el lado del administrador.

Vaya a su archivo functions.php y agregue el siguiente código al final del archivo o puede crear su propio complemento para agregar esta función.

//Custom WooCommerce Checkout Fields based on Quantity
add_action( 'woocommerce_before_order_notes', 'person_details' );

function person_details($checkout) {
    global $woocommerce;
$count = $woocommerce->cart->cart_contents_count;
$i = 1;
       for($k=2; $k<= $count; $k++) {
        $i++;
           print ('<h3>Please enter details of attendee '.$i.'</h3>');
        woocommerce_form_field( 'cstm_full_name'.$i, array(
            'type'          => 'text',
            'class'         => array('my-field-class form-row-wide'),
            'label'         => __('Full name'),
            'placeholder'   => __('Enter full name'),
            ),
            $checkout->get_value( 'cstm_full_name'.$i ));
        echo '<div class="clear"></div>';
        woocommerce_form_field( 'cstm_phone'.$i, array(
            'type'          => 'text',
            'class'         => array('my-field-class form-row-first'),
            'label'         => __('Phone'),
            'placeholder'   => __('Enter phone number'),
            ),
            $checkout->get_value( 'cstm_phone'.$i ));
        woocommerce_form_field( 'cstm_email'.$i, array(
            'type'          => 'email',
            'class'         => array('my-field-class form-row-last'),
            'label'         => __('Email address'),
            'placeholder'   => __('Enter email address'),
            ),
            $checkout->get_value( 'cstm_email'.$i ));
        echo '<div class="clear"></div>';
        woocommerce_form_field( 'cstm_address'.$i, array(
            'type'          => 'textarea',
            'class'         => array('my-field-class form-row-wide'),
            'label'         => __('Full address'),
            'placeholder'   => __('Enter full address'),
            ),
            $checkout->get_value( 'cstm_address'.$i ));
}
}

/**
 * Save value of fields
 */

add_action('woocommerce_checkout_update_order_meta', 'customise_checkout_field_update_order_meta');

function customise_checkout_field_update_order_meta($order_id)
{
    global $woocommerce;
$count = $woocommerce->cart->cart_contents_count;
$i = 1;
       for($k=2; $k<= $count; $k++) {
        $i++;
    if (!empty($_POST['cstm_full_name'.$i])) {
        update_post_meta($order_id, 'Name of Attendee'.$i, sanitize_text_field($_POST['cstm_full_name'.$i]));
    }
    if (!empty($_POST['cstm_phone'.$i])) {
        update_post_meta($order_id, 'Phone of Attendee'.$i, sanitize_text_field($_POST['cstm_phone'.$i]));
    }
    if (!empty($_POST['cstm_email'.$i])) {
        update_post_meta($order_id, 'Email of Attendee'.$i, sanitize_text_field($_POST['cstm_email'.$i]));
    }
    if (!empty($_POST['cstm_address'.$i])) {
        update_post_meta($order_id, 'Address of Attendee'.$i, sanitize_text_field($_POST['cstm_address'.$i]));
    }
}
}

Campos personalizados dinámicos en la página de pago
ingrese la descripción de la imagen aquí

Valor de campos personalizados en la página de pedido en admin
ingrese la descripción de la imagen aquí

Referencia

Según la respuesta de @HMagby, mi versión administra múltiples campos para cada artículo en el carrito y para cada cantidad. Los valores de campo se guardan como order item meta después de realizar el pedido. Ideal para el comercio electrónico de venta de entradas.

<?php
class MRL_Utils
{
    private $products_ids = false;
    private $personal_data = false;
    
    public function __construct()
    {    
        // Campi
        $this->personal_data = array(
            "nome" => array("label" => "Nome", "type" => "text", "class" => "my-field-class form-row-first", "required" => true, "placeholder" => "Inserisci il nome del partecipante"),
            'tel' => array("label" => "Cellulare", "type" => "tel", "class" => "my-field-class form-row-last", "required" => false, "placeholder" => "Inserisci il numero di cellulare"),
            'note' => array("label" => "Intolleranze e/o allergie", "type" => "textarea", "class" => "my-field-class form-row-wide", "required" => false, "placeholder" => "Specifica eventuali intolleranze e/o allergie"),
        );
        $this->products_ids = array(32, 33, 34, 35);

        // Form nella pagina del Checkout
        add_action('woocommerce_before_order_notes', array($this, 'mrl_display_personal_data_field'), 10, 1);
        add_action('woocommerce_checkout_update_order_meta', array($this, 'mrl_save_personal_data_field'), 10, 1);        

    }

    public function mrl_save_personal_data_field($order_id)
    {
        $order = wc_get_order($order_id);
        foreach($order->get_items() as $item_id => $item)
        {
            $product_id = $item->get_product_id();
            $quantity = $item->get_quantity();

            // Procedo solo se il prodotto è tra quelli abilitati
            if(in_array($product_id, $this->products_ids))
            {
                // Salvo i dati inseriti come dei meta per ogni item dell'ordine
                // Ricordiamoci che c'è un solo ITEM anche se la quantità è > 1
                for($i = 0; $i < $quantity; $i++)
                {
                    // So che i dati sono salvati in questo modo: mrl_NAME_ID_#
                    // Dove NAME è la key di $_POST, ID è l'ID del prodotto a catalogo e # è progressivo da 0 a quantità
                    $valori = array();

                    // Per ogni dato personale
                    foreach($this->personal_data as $key => $value)
                    {
                        $label = $value['label'];
                        $selettore = "mrl_".$key."_".$product_id."_".$i;

                        if(isset($_POST[$selettore]))
                        {
                            $valori[$label] = $_POST[$selettore];
                        }
                    }               

                    // Salvo i meta dell'item
                    $valori = implode(', ', array_map(
                        function ($v, $k) { return sprintf("%s: %s", $k, $v); },
                        $valori,
                        array_keys($valori)
                    ));
                    wc_add_order_item_meta($item_id, "#".($i+1), $valori, true);
                    wc_update_order_item_meta($item_id, "#".($i+1), $valori);
                }   
            }         
        }
    }


    public function mrl_display_personal_data_field($checkout)
    {
        global $woocommerce;
        $items = $woocommerce->cart->get_cart();

        foreach($items as $item => $values)
        {
            // Ogni item avrà una sua quantità
            $qty = $values['quantity'];
            $_id = $values['data']->get_id();
            $_product =  wc_get_product($_id);
            $title = $_product->get_title();

            // Procedo solo se il prodotto è tra quelli abilitati
            if(in_array($_id, $this->products_ids))
            {
                echo "<h3>$title ($qty)</h3>";
                for($i = 0; $i < $qty; $i++)
                {
                    echo "<div style="border:5px solid var(--ast-global-color-2);padding:10px;margin-top:10px;margin-bottom:10px;background-color:#fafafa"><h4>#".($i+1)."</h4>";

                    // Per ogni dato personale
                    foreach($this->personal_data as $key => $value)
                    {
                        $type = $value['type'];
                        $label = $value['label'];
                        $class = $value['class'];
                        $required = $value['required'];
                        $placeholder = $value['placeholder'];

                        $selettore = "mrl_".$key."_".$_id."_".$i;
                        woocommerce_form_field($selettore, array(
                                'type'          => $type,
                                'class'         => array($class),
                                'label'         => $label." #".($i+1),
                                'placeholder'   => $placeholder,
                                'required' => $required,
                            ),
                            $checkout->get_value($selettore),
                        );
                    }

                    echo "</div>";
                }
            }
        }
    }
}
add_action('plugins_loaded', function(){
    new MRL_Utils();
});
?>

¿Ha sido útil esta solución?