How to add a custom field on a product and change the price using a custom field

Change cart item prices in WooCommerce code
321 Views

Use Code Added In functions.php:

<?php
// Add Custom Fields in after add to cart button
add_action( 'woocommerce_before_add_to_cart_button', 'cxc_before_add_to_cart_button_custom_field' );
function cxc_before_add_to_cart_button_custom_field() {
	?>
	<div class="woocommerce-variation-add-to-cart variations_button woocommerce-variation-add-to-cart-disabled">
		<table class="variations" cellspacing="0" width="100px">
			<tbody>
				<tr>
					<td colspan="2" style="text-align: center;"><label for="cxc-additional-fields"><?php echo __("Cxc Additional Fields", "cxc-codexcoach"); ?></label></td>
				</tr>
				<tr>
					<td class="label" style="width:100px"><label for="color"><?php echo __("Width", "cxc-codexcoach"); ?></label></td>
					<td class="value">
						<input type="text" name="new-width" value="" required/>
					</td>
				</tr>
				<tr>
					<td class="label"><label for="color"><?php echo __("Hight", "cxc-codexcoach"); ?></label></td>
					<td class="value">
						<input type="text" name="new-height" value="" required/>
					</td>
				</tr>
			</tbody>
		</table>
		<?php
	}
?>

Then you will be able to use woocommerce_add_to_cart_validation hook for field validation

<?php
// Field validation
	add_action( 'woocommerce_add_to_cart_validation', 'cxc_woocommerce_add_to_cart_validation_call_back' );

	function cxc_woocommerce_add_to_cart_validation_call_back( $passed ) {
		$error_notice = array(); // Initializing

		if ( isset($_POST['new-width']) && empty($_POST['new-width']) ) {
			$passed = false;
			$error_notice[] = __('"Width" is a required field', 'cxc-codexcoach');
		}

		if ( isset($_POST['new-height']) && empty($_POST['new-height']) ) {
			$passed = false;
			$error_notice[] = __('"Hight" is a required field', 'cxc-codexcoach');
		}

    	// Display errors notices
		if ( ! empty($error_notice) ) {
			wc_add_notice( implode('<br>', $error_notice), 'error' );
		}

		return $passed;
	}
?>

The following fields must now be saved as custom cart item data and displayed in the shopping cart and checkout pages:

<?php
// Save as custom cart item data
	add_filter( 'woocommerce_add_cart_item_data', 'cxc_woocommerce_add_cart_item_data', 10, 2 );

	function cxc_woocommerce_add_cart_item_data( $cart_item_data, $product_id ) {
		if ( isset($_POST['new-width']) && ! empty($_POST['new-width']) ) {
			$cart_item_data['new-width'] = sanitize_text_field($_POST['new-width']);
		}

		if ( isset($_POST['new-height']) && ! empty($_POST['new-height']) ) {
			$cart_item_data['new-height'] = sanitize_text_field($_POST['new-height']);
		}

		return $cart_item_data;
	}

// Display in cart and checkout
	add_filter( 'woocommerce_get_item_data', 'cxc_display_on_cart_and_checkout', 10, 2 );

	function cxc_display_on_cart_and_checkout( $cart_data, $cart_item ) {
		if ( isset($cart_item['new-width']) ) {
			$cart_data[] = array( "name" => __("Width", "cxc-codexcoach"),  "value" => $cart_item['new-width'] );
		}

		if ( isset($cart_item['new-height']) ) {
			$cart_data[] = array( "name" => __("Hight", "cxc-codexcoach"),  "value" => $cart_item['new-height'] );
		}

		return $cart_data;
	}
?>

You must display the data from the fields in orders and emails after saving them as custom order item data:

<?php
// Display on orders and email notifications (save as custom order item meta data)
	add_action( 'woocommerce_checkout_create_order_line_item', 'cxc_display_on_orders_and_emails', 10, 4 );

	function cxc_display_on_orders_and_emails( $item, $cart_item_key, $values, $order ) {
		if ( isset($values['new-width']) ) {
			$item->add_meta_data( __("Width", "cxc-codexcoach"), $values['new-width'] );
		}

		if ( isset($values['new-height']) ) {
			$item->add_meta_data( __("Hight", "cxc-codexcoach"), $values['new-height'] );
		}

	}
?>

We need to use 2 different hooks:

  • The first one just as yours without trying to change the price in it.
  • The second one where you will change your cart item price.

The code:

<?php
  add_filter( 'woocommerce_add_cart_item', 'cxc_add_custom_cart_item_data', 10, 2 );

	function cxc_add_custom_cart_item_data( $cart_item_data, $cart_item_key ) {

		if( isset( $_POST['new-width'] ) )
			$cart_item_data['new-width'] = $_POST['new-width'];
		if( isset( $_POST['new-height'] ) )
			$cart_item_data['new-height'] = $_POST['new-height'];

		return $cart_item_data;
	}


	add_action( 'woocommerce_before_calculate_totals', 'cxc_set_custom_cart_item_price', 20, 1 );

	function cxc_set_custom_cart_item_price( $cart ) {
		if ( is_admin() && ! defined( 'DOING_AJAX' ) ){
			return;
		}

		if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ){
			return;
		}

    // First loop to check if product 11 is in cart
		foreach ( $cart->get_cart() as $cart_item ){
			if( isset($cart_item['new-width']) && isset($cart_item['new-height']) && ! empty($cart_item['new-width']) && ! empty($cart_item['new-height']) ){
				$cart_item['data']->set_price( 50 );
			}
		}
	}
?>

Code goes in function.php file of your active child theme (or theme) or also in any plugin file.

Was this article helpful?
YesNo

Leave a comment

Your email address will not be published.