Adding Custom Attribute selected value to Cart, Checkout, Order and email notification - php

My Environment is:
- WordPress 4.7.4
- Debian Linux 8
- WooCommerce 3.0.5
- 256M Memory
I've tried a number of solutions including:
Add custom variable to cart content
WooCommerce Show Attributes plugin
However, I'm still not getting the right result and time is of the essence at this point of this project. A precision, I have the same price for all attribute values…
I created a custom single-product.php tempalte with a custom form:
<form id="add-product-form" class="add-product-form form-horizontal" method="post" action="">
<input name="add-to-cart" value="15709" type="hidden">
<div class="form-group color-dropdown">
<label class="col-sm-3 control-label">Color</label>
<select id="color-options" class="col-sm-9 color-select" name="color" required="">
<option value="auburn">Auburn</option>
<option value="black">Black</option>
<option value="mahogany-ash">Mahogany Ash</option>
<option value="mocha">Mocha</option> </select>
</div>
<div class="form-group quantity-area">
<label class="col-sm-3 control-label">Qty.</label>
<input name="quantity" id="quantity" maxlength="2" class="col-sm-9 quantity-input" required="" type="text">
</div>
<button id="submit-to-cart" value="Add to Cart" class="btn btn-a2c submit" name="submit" type="submit"><i class="fa fa-plus" aria-hidden="true"></i> Add to Cart</button>
</form>
This form uses an AJAX post method and adds to cart as intended.
However:
I'm not seeing the color they chose listed on the WC Cart page
I'm not seeing the color they chose listed on the WC Checkout page
I'm not seeing the color they chose on the corresponding emails. I know I have to edit email-order-items.php but I don't know the right approach here.
My question:
So How can I add a Custom Attribute selected value to Cart, Checkout, Order and email notification?
I know I can take the Variable product approach, but even at 256M memory, the Variations menu in the Variable Product area constantly spins so I can never get to this area to Add Variations.

Instead of overriding your template single-product.php, it is better to use the original hook do_action('woocommerce_before_add_to_cart_button'); that are made to inject code in it through some custom hooked function.
As I have understood, you don't need to use a variable product. You want to use a single product that is going to display a custom selector field in which you set an existing "Color" attribute with the chosen values for this product.
Here is that hooked function:
// Add the custom field selector based on attribute "Color" values set in the simple product
add_action( 'woocommerce_before_add_to_cart_button', 'action_before_add_to_cart_button' );
function action_before_add_to_cart_button(){
global $product;
foreach($product->get_attributes() as $attribute_slug => $attribute_obj){
if($attribute_slug == 'pa_color'){
echo '<div class="form-group color-dropdown">
<label class="col-sm-3 control-label" for="custom_pa_color">'. __('Color', 'woocommerce') .'</label>
<select id="custom_pa_color" class="col-sm-9 color-select" name="custom_pa_color" required="">';
foreach( $attribute_obj->get_terms() as $term_obj){
$term_id = $term_obj->id;
$term_name = $term_obj->name;
$term_slug = $term_obj->slug;
echo '<option value="'.$term_slug.'">'.$term_name.'</option>';
}
echo '</select>
</div>';
}
}
}
Then as you want to pass in cart item the selected "Color" attribute "value" when product is added to cart and finally to display it in cart, checkout, order and email notifications here is the code you need:
// Save the custom product custom field data in Cart item
add_action( 'woocommerce_add_cart_item_data', 'save_in_cart_my_custom_product_field', 10, 2 );
function save_in_cart_my_custom_product_field( $cart_item_data, $product_id ) {
if( isset( $_POST['custom_pa_color'] ) ) {
$cart_item_data[ 'custom_pa_color' ] = $_POST['custom_pa_color'];
// When add to cart action make an unique line item
$cart_item_data['unique_key'] = md5( microtime().rand() );
WC()->session->set( 'custom_data', $_POST['custom_pa_color'] );
}
return $cart_item_data;
}
// Render the custom product custom field in cart and checkout
add_filter( 'woocommerce_get_item_data', 'render_custom_field_meta_on_cart_and_checkout', 10, 2 );
function render_custom_field_meta_on_cart_and_checkout( $cart_data, $cart_item ) {
$custom_items = array();
if( !empty( $cart_data ) )
$custom_items = $cart_data;
if( $custom_field_value = $cart_item['custom_pa_color'] )
$custom_items[] = array(
'name' => __( 'Color', 'woocommerce' ),
'value' => $custom_field_value,
'display' => $custom_field_value,
);
return $custom_items;
}
// Add the the product custom field as item meta data in the order + email notifications
add_action( 'woocommerce_add_order_item_meta', 'tshirt_order_meta_handler', 10, 3 );
function tshirt_order_meta_handler( $item_id, $cart_item, $cart_item_key ) {
$custom_field_value = $cart_item['custom_pa_color'];
// We add the custom field value as an attribute for this product
if( ! empty($custom_field_value) )
wc_update_order_item_meta( $item_id, 'pa_color', $custom_field_value );
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code works and is tested for WooCommerce version from 2.5 to 3.0+
In your template
You will have to remove the selector code and to re-insert the oringinal hook:
<form id="add-product-form" class="add-product-form form-horizontal" method="post" action="">
<?php
// Here we re-insert the original hook
do_action('woocommerce_before_add_to_cart_button');
?>
<div class="form-group quantity-area">
<label class="col-sm-3 control-label">Qty.</label>
<input name="quantity" id="quantity" maxlength="2" class="col-sm-9 quantity-input" required="" type="text">
</div>
<button id="submit-to-cart" value="Add to Cart" class="btn btn-a2c submit" name="submit" type="submit"><i class="fa fa-plus" aria-hidden="true"></i> Add to Cart</button>
</form>
Related answer: Saving a product custom field and displaying it in cart page

Related

How do I AJAXify an 'add to cart' button in a variation loop in WooCommerce?

I've cobbled together some PHP snippets so that I can create custom variation loops which display product variations (in this case t-shirt sizes) in a drop down list with a single add to cart button. This works as expected, however I need to add these items to cart via AJAX to improve user experience and performance.
Oddly, the item appears to be added to the cart dynamically but then the page still refreshes itself. I've poked around but just can't seem to work out why, is it the submit event that requires something like preventDefault? Is there a way of handling this page reload in my current code or do I need to reengineer it using a method like this?
/**
* Replace add to cart button in the loop.
*/
function iconic_change_loop_add_to_cart() {
add_action( 'woocommerce_after_shop_loop_item', 'iconic_template_loop_add_to_cart', 50 );
}
add_action( 'init', 'iconic_change_loop_add_to_cart', 10 );
/**
* Use single add to cart button for variable products.
*/
function iconic_template_loop_add_to_cart() {
global $product;
if ( ! $product->is_type( 'variable' ) ) {
woocommerce_template_loop_add_to_cart();
return;
}
remove_action( 'woocommerce_single_variation', 'woocommerce_single_variation_add_to_cart_button', 20 );
add_action( 'woocommerce_single_variation', 'iconic_loop_variation_add_to_cart_button', 90 );
woocommerce_template_single_add_to_cart();
}
/**
* Customise variable add to cart button for loop.
*
* Remove qty selector and simplify.
*/
function iconic_loop_variation_add_to_cart_button() {
global $product;
$variations = $product->get_available_variations();
?>
<div class="woocommerce-variation-add-to-cart variations_button">
<input type="hidden" name="add-to-cart" value="<?php echo absint( $product->get_id() ); ?>" />
<input type="hidden" name="product_id" value="<?php echo absint( $product->get_id() ); ?>" />
<input type="hidden" name="variation_id" class="variation_id" value="0" />
<button type="submit" class="single_add_to_cart_button button"><?php echo esc_html( $product->single_add_to_cart_text() ); ?></button>
</div>
<?php
}

Custom add to cart button doesn't work if manage stock level at product level

I just have a little question on a custom add to cart button I have created on the shop page.
If you view the screenshot below, if you click the add to cart button (the one with the price associated), it will display the options for the user (quantity, variations, add to cart button etc).
However, I notice if a product is set so that it manages stock at product level, the add to cart button (one with price associated) doesn't work (as nothing happens). Not sure why it's not working when this setting is set. Can somebody help?
Here is the code:
/**
* Replace add to cart button in the loop.
*/
function iconic_change_loop_add_to_cart() {
remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10 );
add_action( 'woocommerce_after_shop_loop_item', 'iconic_template_loop_add_to_cart', 10 );
}
add_action( 'init', 'iconic_change_loop_add_to_cart', 10 );
function iconic_template_loop_add_to_cart() {
global $product;
woocommerce_template_single_add_to_cart();
}
/**
* Customise variable add to cart button for loop.
*
* Remove qty selector and simplify.
*/
function iconic_loop_variation_add_to_cart_button() {
global $product;
?>
<div class="woocommerce-variation-add-to-cart variations_button">
<button type="submit" class="single_add_to_cart_button button"><?php echo esc_html( $product->single_add_to_cart_text() ); ?></button>
<input type="hidden" name="add-to-cart" value="<?php echo absint( $product->get_id() ); ?>" />
<input type="hidden" name="product_id" value="<?php echo absint( $product->get_id() ); ?>" />
<input type="hidden" name="variation_id" class="variation_id" value="0" />
</div>
<?php
}
With given little info it is very hard to find the bug. Please follow the below steps -
Hard reload the browser, and check if there are fatal js error in console and resolve those first.
If the add-to-cart button is not appearing for variable product - make sure you have put the price for variation
If the issue is still there - find the code for following hook(s) and edit the question description
woocommerce_product_single_add_to_cart_text
woocommerce_variable_add_to_cart
woocommerce_ajax_variation_threshold
woocommerce_before_variations_form
woocommerce_variation_is_visible
Also as GhostPengy says give us the code from the iconic_loop_variation_add_to_cart_button is called.
Follow the above steps and if it is not resolved give us more code to identify the bug precisely.

WooCommerce - Limit the zip code character limit on the CART page (NOT the checkout/account pages)

So I was able to limit the zip code length limit to 5 on the user's shipping/billing info on their account page as well as the checkout page using this code in my functions.php:
function my_wc_custom_billing_fields( $fields ) {
$fields['billing_postcode']['maxlength'] = 5;
return $fields;
}
add_filter( 'woocommerce_billing_fields', 'my_wc_custom_billing_fields' );
function my_wc_custom_shipping_fields( $fields ) {
$fields['shipping_postcode']['maxlength'] = 5;
return $fields;
}
add_filter( 'woocommerce_shipping_fields', 'my_wc_custom_shipping_fields' );
However, I still am able to enter past the limit in the zip code box on the CART page. You are able to change your address on the cart page and if you click "go to checkout" after typing more than 5 digits, it will allow the form to fill in with those additional digits on the checkout page. I want the zip code box on the CART page to work the same as it does on the other pages.
Thank you for taking to the time to read this. I hope to hear from someone soon!
------- >EDIT: FIGURED IT OUT!
Instead of creating a filter inside my functions.php, I directly edited the woocommerce/templates/cart/shipping-calculator.php file.
In this piece of code:
<?php if ( apply_filters( 'woocommerce_shipping_calculator_enable_postcode', true ) ) : ?>
<p class="form-row form-row-wide" id="calc_shipping_postcode_field">
<input type="text" class="input-text" value="<?php echo esc_attr( WC()->customer->get_shipping_postcode() ); ?>" placeholder="<?php esc_attr_e( 'Postcode / ZIP', 'woocommerce' ); ?>" name="calc_shipping_postcode" id="calc_shipping_postcode" />
</p>
<?php endif; ?>
I simply added "maxlength="5" in the line.
<input type="text" class="input-text" maxlength="5" value="
I hope this helps someone along the way! :)

Add additional fields to Admin User under Customer shipping section in Woocommerce

In woocommerce, after creating and registering some custom account fields in a custom php file using the following code:
<label for="reg_shipping_phone"> ... </label>
<input class="..." id="reg_shipping_phone" name="shipping_phone"
type="tel" pattern="[a-z0-9.-]{6,40}"
title=" ... " placeholder=" ... "
value="<?php esc_attr_e( $_POST['shipping_phone'] ); ?>" />
and in my theme's function.php file:
//save on admin/&frontend on change
add_action( 'personal_options_update', 'woo_save_extra_register_fields' );
add_action( 'woocommerce_save_account_details', 'woo_save_extra_register_fields' );
// Save extra registration fields data on from
add_action( 'woocommerce_created_customer', 'woo_save_extra_register_fields' );
function woo_save_extra_register_fields( $customer_id )
{
if( isset( $_POST['shipping_phone'] ) ) {
update_user_meta( $customer_id, 'shipping_phone', $_POST['shipping_phone'] );
}
}
I would like to implement this "Shipping phone" field in the correct position on Backend User profile pages inside the "Customer's shipping address" section table
How can I insert additional fields in the "Customer's shipping address" section table?
For example I have tried the following *(but 11,5 is wrong...)*:
add_action( 'show_user_profile', 'extra_profile_fields',***11,5*** );
add_action( 'edit_user_profile', 'extra_profile_fields',***11,5*** );
function extra_profile_fields( $user ) { ?>
<h3>NAME OF TABLE</h3>
<table class="form-table">
<tr>
<th><label for="shipping_phone">SHIPPING PHONE</label></th>
<td>
<input type="text" name="shipping_phone" id="shipping_phone" value="<?php echo esc_attr( $user->shipping_phone); ?>" class="regular-text" />
</td>
</tr>
>
</table>
<?php }
Any help is appreciated.
If you want to include your custom "Shipping phone" field in Backend User profile under "Customer's shipping address" section, you will use the following instead:
add_filter( 'woocommerce_customer_meta_fields', 'filter_add_customer_meta_fields', 10, 1 );
function filter_add_customer_meta_fields( $args ) {
$args['shipping']['fields']['shipping_phone'] = array(
'label' => __( 'Shipping phone', 'woocommerce' ),
'description' => '',
);
return $args;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
This little code snippet will do it all. If you change the value in this "Shipping phone" field, it will be updated without needing any additional code.

Add custom checkout fields below the terms and conditions in Woocommerce

I have built an e-commerce site using Woocommerce. I would like to add two more check boxes below the terms and conditions. I have searched everywhere for a working solution and the only thing that I found is a commercial plugin.
How to add custom checkout fields (2 checkboxes) below the terms and conditions programmatically?
Location of the terms and condition screenshot:
The 1st hooked function displays the 2 additional checkout fields
The 2nd hooked function will check that both checkboxes are "selected" to allow checkout, displaying a custom error notice if not…
The code:
add_action('woocommerce_checkout_before_terms_and_conditions', 'checkout_additional_checkboxes');
function checkout_additional_checkboxes( ){
$checkbox1_text = __( "My first checkbox text", "woocommerce" );
$checkbox2_text = __( "My Second checkbox text", "woocommerce" );
?>
<p class="form-row custom-checkboxes">
<label class="woocommerce-form__label checkbox custom-one">
<input type="checkbox" class="woocommerce-form__input woocommerce-form__input-checkbox input-checkbox" name="custom_one" > <span><?php echo $checkbox1_text; ?></span> <span class="required">*</span>
</label>
<label class="woocommerce-form__label checkbox custom-two">
<input type="checkbox" class="woocommerce-form__input woocommerce-form__input-checkbox input-checkbox" name="custom_two" > <span><?php echo $checkbox2_text; ?></span> <span class="required">*</span>
</label>
</p>
<?php
}
add_action('woocommerce_checkout_process', 'my_custom_checkout_field_process');
function my_custom_checkout_field_process() {
// Check if set, if its not set add an error.
if ( ! $_POST['custom_one'] )
wc_add_notice( __( 'You must accept "My first checkbox".' ), 'error' );
if ( ! $_POST['custom_two'] )
wc_add_notice( __( 'You must accept "My second checkbox".' ), 'error' );
}
Code goes in function.php file of your active child theme (active theme).
Tested and works.

Categories