发送带有保存在Woocommerce 3中的其他帐户字段值的自定义电子邮件

时间:2018-10-04 09:07:34

标签: php wordpress woocommerce custom-fields email-notifications

基于插件“ Advanced Custom Fields”,为WooCommerce用户的个人帐户创建了其他字段。使用第二个“ ACF for WooCommerce”插件,我将这些字段放在了“编辑帐户”页面上。

如果用户已填写或编辑了这些字段,则管理员将收到一封包含这些字段值的电子邮件。以下代码负责通知:

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();
}

在这里出现两个错误:

  1. 当用户编辑这些字段时,显然已缓存的旧数据将发送到管理员电子邮件。重新发送而不进行编辑时,您将收到正确的字段数据。

    我输入了一行代码:

    update_meta_cache('user', $user_id);
    

    但是它不起作用,旧数据仍在继续。显然我做错了。

  2. 所有字段的数据都正确存储在数据库中,并且也正确显示在发给管理员的电子邮件中。复选框有问题。

    在这种情况下,“您喜欢哪种风格?”将显示三个复选框“经典”,“休闲”和“运动”。用户选择了“休闲”复选框。该字段的值已正确存储在数据库中。

    但是在发给管理员的电子邮件中,只有这个单词“ Array”代替了这个值。

告诉我如何解决?

感谢您的帮助。

1 个答案:

答案 0 :(得分:3)

更新1-解决插件问题。

1)缓存问题:我终于在“ ACF for WooCommerce”插件源代码中找到了问题。

  

您需要使用更高的优先级值,因为插件使用的优先级为100

因此,您将在代码中替换(在构造函数中):

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

150 的优先级值(或更多)例如:

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

它应该彻底解决您的假“缓存”问题(感谢Kashalo)


2)“您喜欢哪种风格?”的复选框字段

您需要将数组转换为具有逗号分隔值的字符串…

使用以下内容:

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 );
}

原始答案:

  

在此问题提供的信息和代码中无法进行测试并尝试重现您的问题,因为没人能猜出您的ACF设置和相关上下文。

     为此,

使用高级自定义字段不是一个好主意。您正在浪费太多时间,试图找出一段时间以来的问题所在。

     

最好的方法是编写自定义字段代码,而不像开发人员那样使用插件。

在以下代码中,我是:

  1. 在CLASS本身中添加并显示其他字段不使用ACF
  2. 验证字段数据,
  3. 保存数据并使用正确的数据发送电子邮件通知(没有任何缓存问题)
  4. 在woocommerce结算部分的Admin用户编辑页面中显示这些其他字段。
  

现在,由于您没有为“家庭” 选择字段和“首选样式” 复选框提供选项值,因此您将必须在每个数组中的设置部分。

     

测试此代码时,您将不得不禁用相关的ACF字段。

完整的功能代码(不带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();
}

代码进入您的活动子主题(活动主题)的function.php文件中。经过测试,可以正常工作。

  

电话字段同时更新用户电话用户计费电话


“我的帐户”>“帐户详细信息”部分中的其他字段:

enter image description here


字段验证:

enter image description here


电子邮件通知(位于“保存更改”上),其中包含新保存的数据:

enter image description here


最后是[帐单]部分下[管理员用户]页面中显示的字段:

enter image description here