Add a custom field to checkout and to my_account user details on registration

一笑奈何 提交于 2019-12-03 16:32:40
LoicTheAztec

— Light Update — (All data is now updated in database)


1) SOLVING THE ERROR:

You have to use update_user_meta() instead of deprecated update_usermeta() to avoid the error.

2) CLEANING AND CHANGING YOUR CODE:

For custom fields, is better to avoid capitals in the slug.

// Add the field to the checkout
add_action( 'woocommerce_after_order_notes', 'birth_day_checkout_field' );
function birth_day_checkout_field( $checkout ) {

    // if customer is logged in and his birth date is defined
    if(!empty(get_user_meta( get_current_user_id(), 'account_birth_date', true ))){
        $checkout_birht_date = esc_attr(get_user_meta( get_current_user_id(), 'account_birth_date', true ));
    }
    // The customer is not logged in or his birth date is NOT defined
    else {
        $checkout_birht_date = $checkout->get_value( 'birth_date' );
    }

    echo '<div id="my_custom_checkout_field">';

    woocommerce_form_field( 'birth_date', array(
        'type'          => 'text',
        'class'         => array('birth-date form-row-wide'),
        'label'         => __( 'Date of Birth', 'theme_domain_slug' ),
        'placeholder'   => __( 'mm/dd/yyyy', 'theme_domain_slug' ),
        ), $checkout_birht_date);

    echo '</div>';

}


// Process the checkout
add_action('woocommerce_checkout_process', 'birth_day_checkout_field_process');
function birth_day_checkout_field_process() {
    // Check if set, if its not set add an error.
    if ( ! $_POST['birth_date'] )
        wc_add_notice( __( 'Please enter your date of birth.', 'theme_domain_slug' ), 'error' );
}


// update order meta with field value
add_action( 'woocommerce_checkout_update_order_meta', 'birth_day_checkout_field_update_order_meta' );
function birth_day_checkout_field_update_order_meta( $order_id ) {
    if (!empty( $_POST['birth_date'])){
        update_post_meta( $order_id, 'birth_date', sanitize_text_field( $_POST['birth_date'] ) );

        // updating user meta (for customer my account edit details page post data)
        update_user_meta( get_post_meta( $order_id, '_customer_user', true ), 'account_birth_date', sanitize_text_field($_POST['birth_date']) );
    }
}

// update user meta with Birth date (in checkout and my account edit details pages)
add_action ( 'personal_options_update', 'birth_day_save_extra_profile_fields' );
add_action ( 'edit_user_profile_update', 'birth_day_save_extra_profile_fields' );
add_action( 'woocommerce_save_account_details', 'birth_day_save_extra_profile_fields' );
function birth_day_save_extra_profile_fields( $user_id )
{
    // for checkout page post data
    if ( isset($_POST['birth_date']) ) {
        update_user_meta( $user_id, 'account_birth_date', sanitize_text_field($_POST['birth_date']) );
    }
    // for customer my account edit details page post data
    if ( isset($_POST['account_birth_date']) ) {
        update_user_meta( $user_id, 'account_birth_date', sanitize_text_field($_POST['account_birth_date']) );
    }
}


// Display field value on the order edit page
add_action( 'woocommerce_admin_order_data_after_billing_address', 'birth_day_checkout_field_display_admin_order_meta', 10, 1 );
add_action ( 'show_user_profile', 'birth_day_checkout_field_display_admin_order_meta' );
add_action ( 'edit_user_profile', 'birth_day_checkout_field_display_admin_order_meta' );
function birth_day_checkout_field_display_admin_order_meta($order){
    echo '<p><strong>' . __( 'Birth date:', 'theme_domain_slug' ) . '</strong> ' . get_post_meta( $order->id, 'birth_date', true ) . '</p>';
}

3) ADDING THE FIELD TO CUSTOMER MY ACCOUNT EDIT DETAILS:

You could have used the woocommerce_edit_account_form_start hook to insert this custom field in customer my_account edit details page, but you don't have the control in placement and ordering.

It's better to included it your active theme woocommerce template folder my_account/form-edit-account.php (if you don't have this folder yet, read Overriding Templates via a Theme, to understand how you can do it.

Here the Birth Date custom field with be located on right side of the email address in My account edit account details form.

Here is the code of this customized template:

<?php
/**
 * Edit account form
 *
 * This template can be overridden by copying it to yourtheme/woocommerce/myaccount/form-edit-account.php.
 *
 * HOWEVER, on occasion WooCommerce will need to update template files and you
 * (the theme developer) will need to copy the new files to your theme to
 * maintain compatibility. We try to do this as little as possible, but it does
 * happen. When this occurs the version of the template file will be bumped and
 * the readme will list any important changes.
 *
 * @see     https://docs.woocommerce.com/document/template-structure/
 * @author  WooThemes
 * @package WooCommerce/Templates
 * @version 2.6.0
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

do_action( 'woocommerce_before_edit_account_form' ); ?>

<form class="woocommerce-EditAccountForm edit-account" action="" method="post">

    <?php do_action( 'woocommerce_edit_account_form_start' ); ?>

    <p class="woocommerce-FormRow woocommerce-FormRow--first form-row form-row-first">
        <label for="account_first_name"><?php _e( 'First name', 'woocommerce' ); ?> <span class="required">*</span></label>
        <input type="text" class="woocommerce-Input woocommerce-Input--text input-text" name="account_first_name" id="account_first_name" value="<?php echo esc_attr( $user->first_name ); ?>" />
    </p>
    <p class="woocommerce-FormRow woocommerce-FormRow--last form-row form-row-last">
        <label for="account_last_name"><?php _e( 'Last name', 'woocommerce' ); ?> <span class="required">*</span></label>
        <input type="text" class="woocommerce-Input woocommerce-Input--text input-text" name="account_last_name" id="account_last_name" value="<?php echo esc_attr( $user->last_name ); ?>" />
    </p>
    <div class="clear"></div>

    <!-- class modification here in <p> tag -->
    <p class="woocommerce-FormRow woocommerce-FormRow--wide form-row form-row-first"><?php // <== Changed the class from "form-row-wide" to "form-row-first" ?>
        <label for="account_email"><?php _e( 'Email address', 'woocommerce' ); ?> <span class="required">*</span></label>
        <input type="email" class="woocommerce-Input woocommerce-Input--email input-text" name="account_email" id="account_email" value="<?php echo esc_attr( $user->user_email ); ?>" />
    </p>
    <!-- (BEGIN) ADDED: Birth day field -->
    <p class="woocommerce-FormRow woocommerce-FormRow--last form-row form-row-last">
        <label for="account_birth_date"><?php _e( 'Birth date', 'theme_domain_slug' ); ?> <span class="required">*</span></label>
        <input type="text" class="woocommerce-Input woocommerce-Input--email input-text" name="account_birth_date" id="account_birth_date" placeholder="mm/dd/yyyy" value="<?php echo esc_attr(get_user_meta( $user->ID, 'account_birth_date', true )); ?>" />
    </p>
    <div class="clear"></div>
    <!-- (END) Birth day field -->

    <fieldset>
        <legend><?php _e( 'Password Change', 'woocommerce' ); ?></legend>

        <p class="woocommerce-FormRow woocommerce-FormRow--wide form-row form-row-wide">
            <label for="password_current"><?php _e( 'Current Password (leave blank to leave unchanged)', 'woocommerce' ); ?></label>
            <input type="password" class="woocommerce-Input woocommerce-Input--password input-text" name="password_current" id="password_current" />
        </p>
        <p class="woocommerce-FormRow woocommerce-FormRow--wide form-row form-row-wide">
            <label for="password_1"><?php _e( 'New Password (leave blank to leave unchanged)', 'woocommerce' ); ?></label>
            <input type="password" class="woocommerce-Input woocommerce-Input--password input-text" name="password_1" id="password_1" />
        </p>
        <p class="woocommerce-FormRow woocommerce-FormRow--wide form-row form-row-wide">
            <label for="password_2"><?php _e( 'Confirm New Password', 'woocommerce' ); ?></label>
            <input type="password" class="woocommerce-Input woocommerce-Input--password input-text" name="password_2" id="password_2" />
        </p>
    </fieldset>
    <div class="clear"></div>

    <?php do_action( 'woocommerce_edit_account_form' ); ?>

    <p>
        <?php wp_nonce_field( 'save_account_details' ); ?>
        <input type="submit" class="woocommerce-Button button" name="save_account_details" value="<?php esc_attr_e( 'Save changes', 'woocommerce' ); ?>" />
        <input type="hidden" name="action" value="save_account_details" />
    </p>

    <?php do_action( 'woocommerce_edit_account_form_end' ); ?>
</form>

<?php do_action( 'woocommerce_after_edit_account_form' ); ?>

4) THANKS GIVING BONUS GIFT: ADDING THE FIELD TO ADMIN EDIT USER:

// ADDING CUSTOM FIELD TO INDIVIDUAL USER SETTINGS PAGE IN BACKEND
add_action( 'show_user_profile', 'add_extra_birth_date' );
add_action( 'edit_user_profile', 'add_extra_birth_date' );
function add_extra_birth_date( $user )
{
    ?>
        <h3><?php _e("Birth Date", "theme_domain_slug"); ?></h3>
        <table class="form-table">
            <tr>
                <th><label for="birth_date_profile"><?php _e("Date", "theme_domain_slug"); ?> </label></th>
                <td><input type="text" name="account_birth_date" value="<?php echo esc_attr(get_user_meta( $user->ID, 'account_birth_date', true )); ?>" class="regular-text" /></td>
            </tr>
        </table>
        <br />
    <?php
}

add_action( 'personal_options_update', 'save_extra_birth_date' );
add_action( 'edit_user_profile_update', 'save_extra_birth_date' );
function save_extra_birth_date( $user_id )
{
    update_user_meta( $user_id, 'account_birth_date', sanitize_text_field( $_POST['account_birth_date'] ) );
}

All the code goes in function.php file of your active child theme (or theme) or also in any plugin file, (except for the template code).

This code is tested and works.

The simplest way to achieve your goal is to update user meta while updating order meta.

/**
 * update order meta with field value
 */

add_action( 'woocommerce_checkout_update_order_meta', 'my_custom_checkout_field_update_order_meta' );


function my_custom_checkout_field_update_order_meta( $order_id ) {
    if ( ! empty( $_POST['birthdate'] ) ) {

        update_post_meta( $order_id, 'Birthdate', sanitize_text_field( $_POST['birthdate'] ) );

        $order = WC_Order( $order_id );    // getting order object
        $user_id = $order->get_user_id();  // getting user id
        if ( $user_id != 0 ) {             // check if user is not a guest
            update_usermeta( $user_id, 'Birthdate', sanitize_text_field( $_POST['birthdate'] ) );
        }
    }
}

You should also delete "update user meta with birthdate" section.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!