Support » Code oplossingen gezocht » Vrije input tekst voor WooCommerce producten

  • Opgelost Bouke Lourens

    (@dewebdeveloper)


    Voor een webshop dat ik heb ontwikkeld met WooCommerce, was ik opzoek naar een extra invoerveld waar klanten tekst kunnen invoeren voor het bedrukken van een label die wij op de sportprijzen kunnen plakken/graveren.

    Nu is het gelukt om dit veld in te voeren, en het is ook gelukt om hiervoor een fee in te stellen. Het kost bijvoorbeeld 0,50 per label. Echter wanneer ik twee of drie keer een product bestel, met drie keer een label in te vullen, worden er maar 1x deze fee doorberekend, waardoor je dus in je winkelmand ziet staan: 3 producten met 3x een eigen ingevoerde tekst, terwijl er maar 1x een fee van 0,50 wordt berekend.

    Zelf hebben we het script van Business Bloomer gebruikt, om dit mogelijk te maken:

    // -----------------------------------------
    // 1. Show custom input field above Add to Cart
     
    add_action( 'woocommerce_before_add_to_cart_button', 'bbloomer_product_add_on', 9 );
     
    function bbloomer_product_add_on() {
        $value = isset( $_POST['custom_text_add_on'] ) ? sanitize_text_field( $_POST['custom_text_add_on'] ) : '';
        echo '<div><label>Custom Text Add-On <abbr class="required" title="required">*</abbr></label><p><input name="custom_text_add_on" value="' . $value . '"></p></div>';
    }
     
    // -----------------------------------------
    // 2. Throw error if custom input field empty
     
    add_filter( 'woocommerce_add_to_cart_validation', 'bbloomer_product_add_on_validation', 10, 3 );
     
    function bbloomer_product_add_on_validation( $passed, $product_id, $qty ){
       if( isset( $_POST['custom_text_add_on'] ) && sanitize_text_field( $_POST['custom_text_add_on'] ) == '' ) {
          wc_add_notice( 'Custom Text Add-On is a required field', 'error' );
          $passed = false;
       }
       return $passed;
    }
     
    // -----------------------------------------
    // 3. Save custom input field value into cart item data
     
    add_filter( 'woocommerce_add_cart_item_data', 'bbloomer_product_add_on_cart_item_data', 10, 2 );
     
    function bbloomer_product_add_on_cart_item_data( $cart_item, $product_id ){
        if( isset( $_POST['custom_text_add_on'] ) ) {
            $cart_item['custom_text_add_on'] = sanitize_text_field( $_POST['custom_text_add_on'] );
        }
        return $cart_item;
    }
     
    // -----------------------------------------
    // 4. Display custom input field value @ Cart
     
    add_filter( 'woocommerce_get_item_data', 'bbloomer_product_add_on_display_cart', 10, 2 );
     
    function bbloomer_product_add_on_display_cart( $data, $cart_item ) {
        if ( isset( $cart_item['custom_text_add_on'] ) ){
            $data[] = array(
                'name' => 'Custom Text Add-On',
                'value' => sanitize_text_field( $cart_item['custom_text_add_on'] )
            );
        }
        return $data;
    }
     
    // -----------------------------------------
    // 5. Save custom input field value into order item meta
     
    add_action( 'woocommerce_add_order_item_meta', 'bbloomer_product_add_on_order_item_meta', 10, 2 );
     
    function bbloomer_product_add_on_order_item_meta( $item_id, $values ) {
        if ( ! empty( $values['custom_text_add_on'] ) ) {
            wc_add_order_item_meta( $item_id, 'Custom Text Add-On', $values['custom_text_add_on'], true );
        }
    }
     
    // -----------------------------------------
    // 6. Display custom input field value into order table
     
    add_filter( 'woocommerce_order_item_product', 'bbloomer_product_add_on_display_order', 10, 2 );
     
    function bbloomer_product_add_on_display_order( $cart_item, $order_item ){
        if( isset( $order_item['custom_text_add_on'] ) ){
            $cart_item['custom_text_add_on'] = $order_item['custom_text_add_on'];
        }
        return $cart_item;
    }
     
    // -----------------------------------------
    // 7. Display custom input field value into order emails
     
    add_filter( 'woocommerce_email_order_meta_fields', 'bbloomer_product_add_on_display_emails' );
     
    function bbloomer_product_add_on_display_emails( $fields ) { 
        $fields['custom_text_add_on'] = 'Custom Text Add-On';
        return $fields; 
    }

    En de onderstaande snippet zorgt er nu voor dat er maximaal 1x een fee wordt berekend, ik vroeg me af wat er in onderstaande snippet aangepast zou moeten worden om het wel voor ieder product door te berekenen.

    add_action( 'woocommerce_cart_calculate_fees', 'bbloomer_add_checkout_fee' );
    
    function bbloomer_add_checkout_fee() {
       foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
            if (!empty( $cart_item['custom_text_add_on'] ) ) {
               WC()->cart->add_fee( 'Bedrukken van label', 0.50 );
                break;
            }
        }
    }
8 reacties aan het bekijken - 1 tot 8 (van in totaal 8)
  • Guido

    (@guido07111975)

    Hoi Bouke,

    Van die onderste functie kun je dan dit maken:

    
    add_action( 'woocommerce_cart_calculate_fees', 'bbloomer_add_checkout_fee' );
    
    function bbloomer_add_checkout_fee() {
    	foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
    		if (!empty( $cart_item['custom_text_add_on'] ) ) {
    			$total = WC()->cart->cart_contents_count * 0.50;
    			WC()->cart->add_fee( 'Bedrukken van label', $total );
    			break;
    		}
    	}
    }
    

    Aantal producten in winkelmand x de fee van 50 cent.

    Guido

    • Deze reactie is gewijzigd 3 weken, 5 dagen geleden door Guido. Reden: Let op: snippet aangepast
    Thread starter Bouke Lourens

    (@dewebdeveloper)

    Hi Guido!

    Thanks! Door het script aan te passen naar wat u voorstelde werkt het optellen nu goed.

    Hier los van, telt hij nu ook een fee op van de producten waarbij niets is opgegeven bij het label. Ik vermoed dat ik dit kan afvangen door het script pas in te laden vanaf het moment dat een klant kiest voor een product waarbij hij het label kan invullen. Dit zou ik dan kunnen instellen in de optie “Variaties” > “Product eigenschap kiezen voor product waarbij de klant dus het label in kan vullen” > En hier vervolgens bij “Beschrijving” het script neer te zetten. Met beschrijving bedoel ik de volgende class “.woocommerce-variation-description”.

    Echter wanneer ik hier een script in wil plakken, wordt dit als platte tekst weergegeven. Is er een mogelijkheid om in de optie “Beschrijving” een mogelijkheid tot het toevoegen van een script?

    Het is mij wel gelukt om bijvoorbeeld een extra invoerveld bij het variabele product in te stellen. Hiervoor gebruik ik het volgende script, en heb ik in mijn functions.php geplaatst:

    // -----------------------------------------
    // 1. Add custom field input @ Product Data > Variations > Single Variation
     
    add_action( 'woocommerce_variation_options_pricing', 'bbloomer_add_custom_field_to_variations', 10, 3 );
     
    function bbloomer_add_custom_field_to_variations( $loop, $variation_data, $variation ) {
       woocommerce_wp_text_input( array(
    'id' => 'custom_field[' . $loop . ']',
    'class' => 'short',
    'label' => __( 'Custom Field', 'woocommerce' ),
    'value' => get_post_meta( $variation->ID, 'custom_field', true )
       ) );
    }
     
    // -----------------------------------------
    // 2. Save custom field on product variation save
     
    add_action( 'woocommerce_save_product_variation', 'bbloomer_save_custom_field_variations', 10, 2 );
     
    function bbloomer_save_custom_field_variations( $variation_id, $i ) {
       $custom_field = $_POST['custom_field'][$i];
       if ( isset( $custom_field ) ) update_post_meta( $variation_id, 'custom_field', esc_attr( $custom_field ) );
    }
     
    // -----------------------------------------
    // 3. Store custom field value into variation data
     
    add_filter( 'woocommerce_available_variation', 'bbloomer_add_custom_field_variation_data' );
     
    function bbloomer_add_custom_field_variation_data( $variations ) {
       $variations['custom_field'] = '<div class="woocommerce_custom_field">Custom Field: <span>' . get_post_meta( $variations[ 'variation_id' ], 'custom_field', true ) . '</span></div>';
       return $variations;
    }

    En tot slot dit in het bestand “variation.php” dat staat in de map “woocommerce/single-product/add-to-cart/variation.php”:

    <script type="text/template" id="tmpl-variation-template">
    <div class="woocommerce-variation-description">
    <code>data.variation.variation_description</code>
    </div>
     
    <div class="woocommerce-variation-price">
    <code>data.variation.price_html</code>
    </div>
     
    <div class="woocommerce-variation-custom_field">
    <code>data.variation.custom_field</code>
    </div>
     
    <div class="woocommerce-variation-availability">
    <code>data.variation.availability_html</code>
    </div>
    </script>

    Ik ben benieuwd of dit makkelijk op te lossen is. Nogmaals bedankt voor het vorig antwoord! Hier ben ik al goed mee op weg geholpen!

    P.S. Hier nog een linkje naar de testomgeving zelf

    • Deze reactie is gewijzigd 3 weken, 5 dagen geleden door Bouke Lourens.
    • Deze reactie is gewijzigd 3 weken, 5 dagen geleden door Bouke Lourens. Reden: Moest ook nog een linkje toevoegen
    Guido

    (@guido07111975)

    Hoi Bouke,

    Ik denk dat je beter een check kunt doen op het laatst, dat alleen items meetellen die een label hebben. Dus dit stukje van mijn fix moet dan anders, want die haalt alle items op:

    
    $total = WC()->cart->cart_contents_count * 0.50;
    

    Nu even geen tijd, ik kom er later even op terug.

    Guido

    Guido

    (@guido07111975)

    Hoi,

    Ik doe dit allemaal ook maar voor hobby, dus weet niet alles 😉

    Met wat hieronder staat wordt er alleen 50 cent berekend voor producten die een label hebben:

    
    add_action( 'woocommerce_cart_calculate_fees', 'bbloomer_add_checkout_fee' );
    
    function bbloomer_add_checkout_fee() {
    	$count = 0; 
    	foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
    		if (!empty( $cart_item['custom_text_add_on'] ) ) {
    			$count++; 
    		}
    	}
    	if ($count > 0) {
    		$total = $count * 0.50;
    		WC()->cart->add_fee( 'Bedrukken van label', $total );
    	}		
    }
    

    Probleem hiermee is dat als je het aantal wijzigt van hetzelfde product, hij maar 1 keer 50 cent voor dat product rekent.

    Sowieso raadzaam om labelveld alleen te tonen bij de juiste producten. Ook omdat hij verplicht ingevuld moet worden.

    Guido

    Thread starter Bouke Lourens

    (@dewebdeveloper)

    Hi Guido,

    Nogmaals bedankt voor het meedenken! Zojuist heb ik de code snippet doet wat het moet doen.

    Sowieso raadzaam om labelveld alleen te tonen bij de juiste producten. Ook omdat hij verplicht ingevuld moet worden.

    Heb je ook enig idee wat een oplossing kan zijn om dit invoerveld enkel weer te geven bij een variabel label, als de klant zeg maar voor ‘Graveren’ kiest. Het product is namelijk ook zonder te graveren te bestellen.

    Bouke

    Guido

    (@guido07111975)

    Hoi,

    Het maakt het veel lastiger als je hetzelfde product ook kunt bestellen zónder label. Dan moeten er dus nog extra checks worden ingebouwd. Je zou het verplicht invullen uit je code kunnen halen.

    En als je het veld alleen bij bepaalde producten wilt tonen, zou je een extra voorwaarde kunnen inbouwen zodat deze alleen getoond wordt bij een bepaalde categorie. Hiervoor moet je een extra check in het eerste deel vd code inbouwen. Dit voorbeeld toont veld alleen als de product categorie (slug) “camera” is:

    
    // -----------------------------------------
    // 1. Show custom input field above Add to Cart
     
    add_action( 'woocommerce_before_add_to_cart_button', 'bbloomer_product_add_on', 9 );
     
    function bbloomer_product_add_on() {
    	if( has_term( 'camera', 'product_cat' ) ) {
    		$value = isset( $_POST['custom_text_add_on'] ) ? sanitize_text_field( $_POST['custom_text_add_on'] ) : '';
    		echo '<div><label>Custom Text Add-On <abbr class="required" title="required">*</abbr></label><p><input name="custom_text_add_on" value="' . $value . '"></p></div>';
    	}
    }
    

    Guido

    Thread starter Bouke Lourens

    (@dewebdeveloper)

    Guido, nogmaals super bedankt voor het meedenken! Hier moet ik verder wel uitkomen. Ik zal daarom dit topic sluiten.

    Fijn weekend gewenst!

    Guido

    (@guido07111975)

    Succes ermee verder, goed weekend!

    Guido

8 reacties aan het bekijken - 1 tot 8 (van in totaal 8)