dongmang3961 2018-10-04 09:07
浏览 76
已采纳

在Woocommerce 3中保存时,发送包含其他帐户字段值的自定义电子邮件

On the basis of the plugin “Advanced Custom Fields” additional fields were created for the personal account of WooCommerce users. Using the second "ACF for WooCommerce" plugin, I placed these fields on the edit-account page.

If the user has filled in the fields or edited them, the administrator will receive an email with the values of these fields. The following code is responsible for notifications:

if (!class_exists('WooCommerceNotifyChanges')) {

    class WooCommerceNotifyChanges {

        function __construct() {                        
            add_action('woocommerce_save_account_details', array($this, 'woocommerce_send_notification'), 15, 1);
        }

        function woocommerce_send_notification($user_id) {
            $body = '';
            $to = 'info@domain.com'; 
            $subject = 'Edit profile data';

            update_meta_cache('user', $user_id); // delete cache   

            $user = new WP_User($user_id);
            $user_name = $user->user_login;

            $body .= '<table>';
            $body .= '<tr><td>'.__("Profile"). '</td></tr>';                        
            $body .= '<tr><td>Login: </td><td>'.$user_name. '</td></tr>';
            $body .= '<tr><td>First Name: </td><td>'.$user->billing_first_name. '</td></tr>';
            $body .= '<tr><td>Last Name: </td><td>'.$user->billing_last_name. '</td></tr>';
            $body .= '<tr><td>Phone: </td><td>'.get_user_meta($user_id, 'field_5b4640119354c', $single=true). '</td></tr>'; //text field
            $body .= '<tr><td>Age: </td><td>'.get_user_meta($user_id, 'field_5b462d304b101', $single=true). '</td></tr>'; //text field
            $body .= '<tr><td>Family: </td><td>'.get_user_meta($user_id, 'field_5b4bd7d9f0031', $single=true). '</td></tr>'; // selector                       
            $body .= '<tr><td>What style do you prefer? </td><td>'.get_user_meta($user_id, 'field_5b47917a378ed', $single=true). '</td></tr>'; // checkbox                      

            $body .= '</table>';

            //set content type as HTML
            $headers = array('Content-Type: text/html; charset=UTF-8;');

            //send email
            if (wp_mail($to, $subject, $body, $headers)) {
                //echo 'email sent';
            } else {
                //echo 'email NOT sent';                
            }
            //exit();
        }
    }
    new WooCommerceNotifyChanges();
}

Here two errors occur:

  1. When a user edits these fields, old, apparently cached data is sent to the administrator email. When you re-send without editing, you will receive the correct field data.

    I put a line of code:

    update_meta_cache('user', $user_id);
    

    But it does not work, the old data is still coming. Apparently, I did something wrong.

  2. The data of all fields are correctly stored in the database and also correctly displayed in an email to the administrator. The problem with checkboxes.

    In this case, the "What style do you prefer?" three checkboxes "Classic", "Casual" and "Sport" are displayed. The user selected the "Casual" checkbox. The value of this field is correctly stored in the database.

    But in the email to the administrator, instead of this value, only the word “Array” comes.

Tell me how to fix it?

Any help is appreciated.

  • 写回答

1条回答 默认 最新

  • dsieyx2015 2018-10-07 03:57
    关注

    Update 1 - Solving the plugin problems.

    1) Caching issue: I finally found the problem in "ACF for WooCommerce" plugin source code.

    You need to use a higher priority value as the plugin uses a priority of 100

    So your in your code you will replace (in the constructor):

    add_action('woocommerce_save_account_details', array($this, 'woocommerce_send_notification'), 15, 1);
    

    by a priority value of 150 (or more) for example:

    add_action('woocommerce_save_account_details', array($this, 'woocommerce_send_notification'), 150, 1);
    

    It should solve definitively your fake "caching" issue (Thanks to Kashalo).


    2) The checkboxes fields for "What style do you prefer?".

    You need to convert the array to a string with coma separated values…

    Use the following:

    function woocommerce_send_notification($user_id) {
        // Recipient
        $to = 'info@domain.com'; 
    
        $subject = 'Edit profile data';
    
        $user =      new WP_User($user_id);
        $user_name = $user->user_login;
    
        $phone  = get_user_meta( $user_id, 'field_5b4640119354c', true ); // Phone - text field
        $age    = get_user_meta( $user_id, 'field_5b462d304b101', true ); // Age- text field
        $family = get_user_meta( $user_id, 'field_5b4bd7d9f0031', true ); // Family - select field 
        $fstyle = get_user_meta( $user_id, 'field_5b47917a378ed', true ); // Favorited styles - Multiple Checkboxes 
    
         // Convert the array to a coma separated list (Favorited styles)
        $fstyle = implode( ', ',  $fstyle ); 
    
        // Body output
        $body = '<h3>'. __("Profile") .'</h3>
        <table>
        <tr><td>Login: </td><td>'.      $user->user_login         .'</td></tr>
        <tr><td>First Name: </td><td>'. $user->billing_first_name .'</td></tr>
        <tr><td>Last Name: </td><td>'.  $user->billing_last_name  .'</td></tr>
        <tr><td>Phone: </td><td>'.      $phone                    .'</td></tr>
        <tr><td>Age: </td><td>'.        $age                      .'</td></tr>
        <tr><td>Family: </td><td>'.     $family                   .'</td></tr>  
        <tr><td>What style do you prefer? </td><td>'. $fstyle     .'</td></tr> 
        </table>';
    
        //set content type as HTML
        $headers = array('Content-Type: text/html; charset=UTF-8;');
    
        //send email
        $sent = wp_mail( $to, $subject, $body, $headers );
    }
    

    Original answer:

    Testing and trying to reproduce your issue is not possible within the provided information and code in this question, as nobody can guess your ACF settings and related context.

    Using Advanced Custom fields is not a good idea for that, when doing multiple customizations. You are loosing so much time, trying to find out what is wrong since a while.

    The best way is to hand code custom fields without using a plugin as developers do.

    In the following code I am:

    1. Adding and displaying the additional fields in the CLASS itself without ACF,
    2. Validating the fields data,
    3. Saving the data and sending the email notification with the correct data (without any cache problem),
    4. displaying those additional fields in Admin user edit pages under woocommerce billing section.

    Now as you dont give the option values for the "Family" select field and for the "Preferred style" checkboxes, you will have to set the desired values in the settings section in each array.

    When testing this code you will have to disable the related ACF fields.

    The complete functional code (without ACF):

    if ( ! class_exists('WC_Additional_Account_fields') ) {
    
        class WC_Additional_Account_fields {
            // 1. Constructor
            function __construct() {
    
                ## A. Settings
    
                // The text domain
                $this->text_domain    = 'aafields';
    
                // The current user WP_User object
                $this->user           = wp_get_current_user();
    
                // The Admin email
                $this->admin_email    = get_option('admin_email');
    
                // The array of options for "Family" and "preferred style"
                $this->fields_options = array(
                    // FAMILY available options array
                    'family' => array(
                        __("No childs", $this->text_domain ),
                        __("One child", $this->text_domain ),
                        __("2 childs", $this->text_domain ),
                        __("3 or more childs", $this->text_domain ),
                    ),
                    // PREFERRED STYLE available options array
                    'preferred_styles' => array(
                        __("Style 1", $this->text_domain ),
                        __("Style 2", $this->text_domain ),
                        __("Style 3", $this->text_domain ),
                        __("Style 4", $this->text_domain ),
                    ),
                );
    
                ## B. Hooking functions
    
                add_action('woocommerce_edit_account_form', array($this, 'add_other_fields_in_edit_account_form') );
                add_action('woocommerce_save_account_details', array($this, 'save_other_fields_in_edit_account_form'), 15, 1);
                add_action('woocommerce_save_account_details_errors', array($this, 'validate_other_fields_in_edit_account_form'), 15, 1 );
                add_filter('woocommerce_customer_meta_fields', array($this, 'add_customer_meta_fields_to_admin_user_list'), 15, 1 );
            }
    
    
            // 1. Displaying additional account fields (+ jQuery script to handle checkboxes as radio buttons)
            public function add_other_fields_in_edit_account_form() {
                $text_domain = $this->text_domain;
                $user        = $this->user;
                $options     = $this->fields_options;
    
                $phone  = isset($user->phone) ? $user->phone : '';
                $age    = isset($user->billing_age) ? $user->billing_age : '';
                $family = isset($user->billing_family) ? $user->billing_family : '';
                $pstyle = isset($user->billing_pref_style) ? $user->billing_pref_style : '';
    
                // Inline styles
                ?>
                <style>
                    #billing_pref_style_field span.label {padding:0 12px 0 6px;}
                    div.clear {clear:both;margin-bottom:1.4em;}
                </style>
                <?php
    
                // Fields 1 and 2
                ?>
                <p class="woocommerce-form-row woocommerce-form-row--first form-row form-row-first">
                    <label for="phone"><?php _e( "Phone number", $text_domain ); ?><span class="required">*</span></label>
                    <input type="text" class="woocommerce-Input woocommerce-Input--text input-text" name="phone" id="phone" value="<?php echo $phone; ?>" />
                </p>
                <p class="woocommerce-form-row woocommerce-form-row--last form-row form-row-last">
                    <label for="billing_age"><?php _e( "Age", $text_domain ); ?><span class="required">*</span></label>
                    <input type="text" class="woocommerce-Input woocommerce-Input--text input-text" name="billing_age" id="billing_age" value="<?php echo $age; ?>" />
                </p>
                <?php
    
                // Fields 3 and 4 (Select field + Grouped checkboxes)
                ?>
                <p class="woocommerce-form-row woocommerce-form-row--last form-row form-row-first">
                    <label for="billing_family"><?php _e( "Family", $text_domain ); ?><span class="required">*</span></label>
                    <select id="billing_family" class="woocommerce-Select woocommerce-Select--option select" name="billing_family">
                        <option value=""><?php _e( "Select a value", $text_domain ); ?></option>
                        <?php
                            foreach( $options['family'] as $option ) :
                                $selected = ( $family == $option ) ? ' selected="selected"' : '';
                                echo '<option value="' . $option . '"' . $selected . '>' . $option . '</option>';
                            endforeach;
                        ?>
                    </select>
                </p>
                <p id="billing_pref_style_field" class="woocommerce-form-row woocommerce-form-row--last form-row form-row-last">
                    <label for="preferred_styles"><?php _e( "What style do you prefer? ", $text_domain ); ?><span class="required">*</span></label>
                        <?php
                            foreach( $options['preferred_styles'] as $key => $option ) :
                                $checked = $pstyle == $option ? ' checked="checked"' : '';
                                echo '<span><input type="checkbox" class="woocommerce-Input woocommerce-Input--checkbox input-checkbox" name="pref_style" value="' . $option . '"' . $checked . '><span class="label">' . $option . '</span></span>';
                            endforeach;
                        ?>
                    </select>
                    <?php $value = ! empty($pstyle) ? $pstyle : $options['preferred_styles'][0];
                    // Hidden field that catch the active checkbox value ?>
                    <input type="hidden"  name="billing_pref_style" value="<?php echo $value; ?>">
                </p>
                <div class="clear"></div>
                <?php
    
                // jQuery code: Enabling grouped checkboxes and passing the chosen value to the hidden field
                ?>
                <script type="text/javascript">
                jQuery(function($){
                    var a = '#billing_pref_style_field',        b = a+' input[type="checkbox"]',
                        c = a+' input[type="hidden"]';
    
                    $(b+'[value="'+$(c).val()+'"]').attr('checked', true);
                    $(b).click( function(){
                        var d = $(this).val();
                        $(c).val(d);
                        $(b).each( function( i, v ) {
                            if( d != $(v).val() ){
                                $(v).prop('checked', false);
                            } else {
                                $(v).prop('checked', true);
                            }
                        });
                    });
                });
                </script>
                <?php
            }
    
            // 2. Additional account fields validation
            public function validate_other_fields_in_edit_account_form( $args ){
                if ( isset($_POST['phone']) && empty($_POST['phone']) )
                    $args->add( 'error', __( 'Please fill in the "Phone" field', 'woocommerce' ),'');
    
                if ( isset($_POST['billing_age']) && empty($_POST['billing_age']) )
                    $args->add( 'error', __( 'Please fill in the "Age" field', 'woocommerce' ),'');
    
                if ( isset($_POST['billing_family']) && empty($_POST['billing_family']) )
                    $args->add( 'error', __( 'Please choose a value for the "Family" field', 'woocommerce' ),'');
    
                if ( isset($_POST['billing_pref_style']) && empty($_POST['billing_pref_style']) )
                    $args->add( 'error', __( 'Please choose a "Preferred style"', 'woocommerce' ),'');
            }
    
            // 3. Save custom additional fields value + Send custom email
            public function save_other_fields_in_edit_account_form( $user_id ) {
                $text_domain = $this->text_domain;
                $send_notification = false;
    
                if( isset( $_POST['phone'] ) ){
                    update_user_meta( $user_id, 'phone', sanitize_text_field( $_POST['phone'] ) );
                    update_user_meta( $user_id, 'billing_phone', sanitize_text_field( $_POST['phone'] ) );
                    if( ! empty( $_POST['phone'] ) )
                        $send_notification = true;
                }
    
                // For Favorite color 2
                if( isset( $_POST['billing_age'] ) ){
                    update_user_meta( $user_id, 'billing_age', sanitize_text_field( $_POST['billing_age'] ) );
                    if( ! empty( $_POST['billing_age'] ) )
                        $send_notification = true;
                }
    
                // For Billing email (added related to your comment)
                if( isset( $_POST['billing_family'] ) ){
                    update_user_meta( $user_id, 'billing_family', esc_attr( $_POST['billing_family'] ) );
                    if( ! empty( $_POST['billing_family'] ) )
                        $send_notification = true;
                }
    
                // For Billing email (added related to your comment)
                if( isset( $_POST['billing_pref_style'] ) ){
                    update_user_meta( $user_id, 'billing_pref_style', esc_attr( $_POST['billing_pref_style'] ) );
                    if( ! empty( $_POST['billing_pref_style'] ) )
                        $send_notification = true;
                }
    
                if( $send_notification ){
                    $user = new WP_User($user_id);
    
                    $to = $this->admin_email;
                    $subject = __('Edited profile data for: ') . $user->billing_first_name . ' ' . $user->billing_last_name;
    
                    $body = '<h3>' . __("Profile", $text_domain ) . '</h3>
                    <table>
                    <tr><th align="left">' . __("Login:", $text_domain ) . '</th><td>'. $user->user_login . '</td></tr>
                    <tr><th align="left">' . __("First Name:", $text_domain ) . ' </th><td>' . $user->billing_first_name . '</td></tr>
                    <tr><th align="left">' . __("Last Name:", $text_domain ) . ' </th><td>' . $user->billing_last_name . '</td></tr>
                    <tr><th align="left">' . __("Phone:", $text_domain ) . ' </th><td>' . $user->phone . '</td></tr>
                    <tr><th align="left">' . __("Age:", $text_domain ) . ' </th><td>' . $user->billing_age . '</td></tr>
                    <tr><th align="left">' . __("Family:", $text_domain ) . ' </th><td>' . $user->billing_family . '</td></tr>
                    <tr><th align="left">' . __("Preferred style", $text_domain ) . ' </th><td>' . $user->billing_pref_style . '</td></tr>
                    </table>';
    
                    //set content type as HTML
                    $headers = array('Content-Type: text/html; charset=UTF-8;');
    
                    //send email
                    wp_mail($to, $subject, $body, $headers);
                }
            }
    
            // 4. Add the additional fields in admin user list in the billing section
            public function add_customer_meta_fields_to_admin_user_list( $args ) {
                $domain  = $this->text_domain;
                $options = $this->fields_options;
    
                // Age
                $args['billing']['fields']['billing_age'] = array(
                    'label'       => __( "Age", $text_domain ),
                    'description' => '',
                );
    
                // Family
                $args['billing']['fields']['billing_family'] = array(
                    'label'       => __( 'Family', 'woocommerce' ),
                    'description' => '',
                    'type'        => 'select',
                    'options'     => array( '' => __( 'Select a value', $domain ) ) + array_combine($options['family'], $options['family']),
                );
    
                // Preferred styles
                $args['billing']['fields']['billing_pref_style'] = array(
                    'label'       => __( 'Preferred styles', 'woocommerce' ),
                    'description' => '',
                    'type'        => 'select',
                    'options'     => array( '' => __( 'Select a value', $domain ) ) + array_combine($options['preferred_styles'], $options['prefered_styles']),
                );
    
                return $args;
            }
        }
        new WC_Additional_Account_fields();
    }
    

    Code goes in function.php file of your active child theme (active theme). Tested and works.

    The phone field updates both user phone and user billing phone at the same time.


    The additional fields on My Account > Account details section:

    enter image description here


    The Fields validation:

    enter image description here


    The email notification (on "Save changes") filled with the fresh saved data:

    enter image description here


    And finally the displayed fields in the Admin users pages under the billing section:

    enter image description here

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 做个有关计算的小程序
  • ¥15 MPI读取tif文件无法正常给各进程分配路径
  • ¥15 如何用MATLAB实现以下三个公式(有相互嵌套)
  • ¥30 关于#算法#的问题:运用EViews第九版本进行一系列计量经济学的时间数列数据回归分析预测问题 求各位帮我解答一下
  • ¥15 setInterval 页面闪烁,怎么解决
  • ¥15 如何让企业微信机器人实现消息汇总整合
  • ¥50 关于#ui#的问题:做yolov8的ui界面出现的问题
  • ¥15 如何用Python爬取各高校教师公开的教育和工作经历
  • ¥15 TLE9879QXA40 电机驱动
  • ¥20 对于工程问题的非线性数学模型进行线性化