我添加了自定义代码来根据自定义购物车中是否有一种或两种产品来生成自定义结账字段。对于每个产品,需要并添加 4 个自定义结账字段。 它们需要并排显示在两列中。
期望的最终结果是:
col1 | col2 |
---|---|
A1 | A2 |
B1 | B2 |
C1 | C2 |
D1 | D2 |
目前,下面的脚本会生成以下内容:
col1 | col2 |
---|---|
A1 | B1 |
C1 | D1 |
A2 | B2 |
C2 | D2 |
function add_custom_checkout_fields_for_product_1234() {
global $woocommerce;
// Get the current cart.
$cart = WC()->cart;
// Product ID to check for.
$product_id_to_check = 5027;
// Calculate the total quantity of the specified product in the cart.
$total_quantity = 0;
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
if ( $cart_item['product_id'] == $product_id_to_check ) {
$total_quantity += $cart_item['quantity'];
}
}
// If the product with ID 1234 is in the cart, add the custom fields based on quantity.
if ( $total_quantity > 0 ) {
echo '<div id="custom_checkout_fields">
<h3>' . __('Custom Fields', 'woocommerce') . '</h3>
<p>' . __('Enter your custom information:', 'woocommerce') . '</p>
<div class="custom-fields-container">';
// Loop to display custom fields based on quantity.
$custom_field_labels = array('A1', 'B1', 'C1', 'D1');
$second_batch_labels = array('A2', 'B2', 'C2', 'D2');
for ( $i = 1; $i <= $total_quantity; $i++ ) {
// Determine which set of labels to use based on even or odd iteration.
$labels = ($i % 2 == 0) ? $second_batch_labels : $custom_field_labels;
foreach ($labels as $label) {
echo '<div class="custom-field">
<label for="custom_field_' . $i . $label . '">' . __('Custom Field', 'woocommerce') . ' ' . $label . ' ' . $i . '</label>
<input type="text" class="input-text" name="custom_field_' . $i . $label . '" id="custom_field_' . $i . $label . '" />
</div>';
}
}
echo '</div></div>';
}
}
add_action('woocommerce_before_checkout_form', 'add_custom_checkout_fields_for_product_1234');
// Validate and save the custom field data.
function validate_and_save_custom_checkout_fields($posted_data) {
// Loop through the posted data to validate custom fields.
for ( $i = 1; $i <= $total_quantity; $i++ ) {
foreach ($custom_field_labels as $label) {
$field_name = 'custom_field_' . $i . $label;
if ( empty( $posted_data[$field_name] ) ) {
wc_add_notice( __('Please fill in all custom fields.', 'woocommerce'), 'error' );
}
}
}
// Return the posted data.
return $posted_data;
}
add_filter('woocommerce_checkout_posted_data', 'validate_and_save_custom_checkout_fields');
此表使用的附加 CSS:
.custom-fields-container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
/* Style custom field columns */
.custom-field {
flex-basis: calc(50% - 10px); /* Adjust width as needed */
margin-bottom: 10px;
box-sizing: border-box;
}
首先,您不能使用
woocommerce_before_checkout_form
钩子添加自定义结帐字段,因为这些字段将位于结帐表单之外(钩子名称是明确的)。
相反,您可以使用
woocommerce_checkout_before_customer_details
钩子来添加结帐字段。
注意: 代码不需要任何 CSS(样式),因为我使用 WooCommerce 结账表单字段。
字段将显示在 2 列中,就像您想要的结果一样。
提交时,字段将被验证并保存到数据库中。
// Utility function: Get specific product total cart item quantity
function get_specific_cart_item_quantity() {
$targeted_id = 5027; // <== Product ID to check for.
$targeted_id = 18; // <== Product ID to check for.
$item_qty = 0; // Initializing
// Loop through cart items
foreach ( WC()->cart->get_cart() as $item ) {
if ( $item['product_id'] == $targeted_id ) {
$item_qty += $item['quantity'];
}
}
return $item_qty;
}
// Add custom checkout fields
add_action('woocommerce_checkout_before_customer_details', 'add_custom_checkout_fields');
function add_custom_checkout_fields() {
$item_qty = get_specific_cart_item_quantity();
if ( $item_qty ) {
$domain = 'woocommerce';
echo '<div id="custom_checkout_fields">
<h3>' . __('Custom Fields', $domain) . '</h3>
<p>' . __('Enter your custom information:', $domain) . '</p>
<div class="custom-fields-container">';
$qty1 = $item_qty % 2 == 0 ? $item_qty / 2 : ( $item_qty == 1 ? 1 : ($item_qty + 1) / 2 );
$qty2 = $item_qty == 1 ? 1 : 2;
// Multi-loop to display custom fields based on quantity in 2 columns
for ( $k = 1; $k <= $qty1; $k++ ) {
$qty2 = $item_qty % 2 != 0 && $k == $qty1 ? 1 : 2;
// 2nd Loop (letters)
foreach ( array('A', 'B', 'C', 'D') as $letter ) {
$key = strtolower($letter);
// 3rd Loop (Columns)
for ( $h = 1; $h <= $qty2; $h++ ) {
$class = $item_qty > 1 ? (($h % 2 == 0) ? 'last' : 'first' ) : 'wide';
$class = $item_qty % 2 != 0 && $k == $qty1 ? 'wide' : $class;
$index = $item_qty == 1 ? 1 : 2;
$index = in_array($class, ['first', 'wide']) ? ($k*2)-1 : $k*2;
$field = "custom_field_{$key}{$index}";
$label = sprintf('%s %s%d', __('Custom Field', $domain), $letter, $index);
woocommerce_form_field( $field, array(
'type' => 'text',
'label' => $label,
'placeholder' => '',
'class' => array('custom-field form-row-'.$class),
'required' => true, // or false
), WC()->checkout->get_value( $field ) );
}
}
}
echo '</div></div>';
}
}
// Validate custom fields
add_action( 'woocommerce_after_checkout_validation', 'validate_custom_checkout_fields', 10, 2 );
function validate_custom_checkout_fields( $data, $errors ) {
if ( did_action('woocommerce_checkout_process') >= 2 ) return;
$item_qty = get_specific_cart_item_quantity();
if ( $item_qty ) {
$domain = 'woocommerce';
$break = false;
// 1st Loop (Letters)
foreach ( array('A', 'B', 'C', 'D') as $letter ) {
$key = strtolower($letter);
// 2nd Loop (Numbers)
for ( $i = 1; $i <= $item_qty; $i++ ) {
$field = "custom_field_{$key}{$i}";
if ( isset($_POST[$field]) && empty($_POST[$field]) ) {
$errors->add( 'validation', __('Please fill in all custom fields.', $domain), 'error' );
$break = true;
break;
}
}
if ( $break ) break;
}
}
}
// Save custom field data as custom order meta data
add_action( 'woocommerce_checkout_create_order', 'save_custom_checkout_fields', 10, 2 );
function save_custom_checkout_fields( $order, $data ) {
$item_qty = get_specific_cart_item_quantity();
if ( $item_qty ) {
$domain = 'woocommerce';
$letters = array('A', 'B', 'C', 'D');
// 1st Loop (Letters)
foreach ( $letters as $letter ) {
$key = strtolower($letter);
// 2nd Loop (Numbers)
for ( $i = 1; $i <= $item_qty; $i++ ) {
$field = "custom_field_{$key}{$i}";
if ( isset($data[$field]) && ! empty($data[$field]) ) {
$order->update_meta_data( $field, sanitize_text_field($data[$field]) );
break;
}
}
}
}
}
代码位于子主题的functions.php 文件中(或插件中)。已测试并有效。