You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WooCommerce编辑账户页面One User Avatar头像无法上传问题排查

问题描述

我使用One User Avatar插件,在WooCommerce的编辑账户(edit-account)页面添加了头像上传功能,但点击「保存更改」按钮后无任何反应。我使用的代码如下:

// Add enctype to form to allow image upload
function action_woocommerce_edit_account_form_tag() {
    echo 'enctype="multipart/form-data"';
} 
add_action( 'woocommerce_edit_account_form_tag', 'action_woocommerce_edit_account_form_tag' );

function action_woocommerce_edit_account_form_start() {
    ?>
    <p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide">
        <input type="file" class="wpua-file" name="wpua-file">
    </p>
    <?php
}
add_action( 'woocommerce_edit_account_form_start', 'action_woocommerce_edit_account_form_start' );

function wpua_action_process_option_updateeee( $user_id ) {
    global  $blog_id,
            $post,
            $wpdb,
            $wp_user_avatar,
            $wpua_force_file_uploader,
            $wpua_resize_crop,
            $wpua_resize_h,
            $wpua_resize_upload,
            $wpua_resize_w,
            $wpua_admin;

    // Check if user has publish_posts capability
    if ( $wp_user_avatar->wpua_is_author_or_above() && ! $wpua_force_file_uploader ) {
        $wpua_id = isset( $_POST['wp-user-avatar'] ) ? absint( $_POST['wp-user-avatar'] ) : 0;

        // Remove old attachment postmeta
        delete_metadata( 'post', null, '_wp_attachment_wp_user_avatar', $user_id, true );

        // Create new attachment postmeta
        add_post_meta( $wpua_id, '_wp_attachment_wp_user_avatar', $user_id );

        // Update usermeta
        update_user_meta( $user_id, $wpdb->get_blog_prefix( $blog_id ) . 'user_avatar', $wpua_id );
    } else {
        // Remove attachment info if avatar is blank
        if ( isset( $_POST['wp-user-avatar'] ) && empty( $_POST['wp-user-avatar'] ) ) {
            // Delete other uploads by user
            $q = array(
                'author'         => $user_id,
                'post_type'      => 'attachment',
                'post_status'    => 'inherit',
                'posts_per_page' => '-1',
                'meta_query'     => array(
                    array(
                        'key'     => '_wp_attachment_wp_user_avatar',
                        'value'   => "",
                        'compare' => '!='
                    ),
                ),
            );

            $avatars_wp_query = new WP_Query( $q );

            while( $avatars_wp_query->have_posts() ) {
                $avatars_wp_query->the_post();

                wp_delete_attachment( $post->ID );
            }

            wp_reset_query();

            // Remove attachment postmeta
            delete_metadata( 'post', null, '_wp_attachment_wp_user_avatar', $user_id, true );

            // Remove usermeta
            update_user_meta( $user_id, $wpdb->get_blog_prefix( $blog_id ) . 'user_avatar', '' );
        }

        // Create attachment from upload
        if ( isset( $_POST['submit'] ) && $_POST['submit'] && ! empty( $_FILES['wpua-file'] ) ) {
            $file = $_FILES['wpua-file'];
            $name = isset( $file['name'] ) ? sanitize_file_name( $file['name'] ) : '';
            $type = isset( $file['type'] ) ? sanitize_mime_type( $file['type'] ) : '';
            $file = wp_handle_upload( $file, array(
                'test_form' => false,
            ) );

            if ( isset( $file['url'] ) ) {
                if ( ! empty( $type ) && preg_match( '/(jpe?g|gif|png)$/i' , $type ) ) {
                    // Resize uploaded image
                    if ( 1 == (bool) $wpua_resize_upload ) {
                        // Original image
                        $uploaded_image = wp_get_image_editor( $file['file'] );

                        // Check for errors
                        if ( ! is_wp_error( $uploaded_image ) ) {
                            // Resize image
                            $uploaded_image->resize( $wpua_resize_w, $wpua_resize_h, $wpua_resize_crop );

                            // Save image
                            $uploaded_image->save( $file['file'] );
                        }
                    }

                    // Break out file info
                    $name_parts = pathinfo( $name );
                    $name       = trim( substr( $name, 0, -( 1 + strlen( $name_parts['extension'] ) ) ) );
                    $url        = $file['url'];
                    $file       = $file['file'];
                    $title      = $name;

                    // Use image exif/iptc data for title if possible
                    if ( $image_meta = @wp_read_image_metadata( $file ) ) {
                        if ( trim( $image_meta['title'] ) && ! is_numeric( sanitize_title( $image_meta['title'] ) ) ) {
                            $title = $image_meta['title'];
                        }
                    }

                    // Construct the attachment array
                    $attachment = array(
                        'guid'           => $url,
                        'post_mime_type' => $type,
                        'post_title'     => $title,
                        'post_content'   => '',
                    );

                    // This should never be set as it would then overwrite an existing attachment
                    if ( isset( $attachment['ID'] ) ) {
                        unset( $attachment['ID'] );
                    }

                    // Save the attachment metadata
                    $attachment_id = wp_insert_attachment( $attachment, $file );

                    if ( ! is_wp_error( $attachment_id ) ) {
                        // Delete other uploads by user
                        $q = array(
                            'author'         => $user_id,
                            'post_type'      => 'attachment',
                            'post_status'    => 'inherit',
                            'posts_per_page' => '-1',
                            'meta_query'     => array(
                                array(
                                    'key'     => '_wp_attachment_wp_user_avatar',
                                    'value'   => '',
                                    'compare' => '!=',
                                ),
                            ),
                        );

                        $avatars_wp_query = new WP_Query( $q );

                        while ( $avatars_wp_query->have_posts() ){
                            $avatars_wp_query->the_post();

                            wp_delete_attachment($post->ID);
                        }

                        wp_reset_query();

                        wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $file ) );

                        // Remove old attachment postmeta
                        delete_metadata( 'post', null, '_wp_attachment_wp_user_avatar', $user_id, true );

                        // Create new attachment postmeta
                        update_post_meta( $attachment_id, '_wp_attachment_wp_user_avatar', $user_id );

                        // Update usermeta
                        update_user_meta( $user_id, $wpdb->get_blog_prefix( $blog_id ) . 'user_avatar', $attachment_id );
                    }
                }
            }
        }
    }
}
add_action( 'woocommerce_save_account_details', 'wpua_action_process_option_updateeee', 10, 1 );

其中wpua_action_process_option_updateeee函数直接取自该插件,我花费了一天时间排查仍未找到错误,请问问题出在哪里?


问题排查与解决方案

核心问题1:提交按钮判断错误

WooCommerce编辑账户页面的提交按钮name属性是save_account_details,而非通用的submit。原代码中isset( $_POST['submit'] )的判断永远不成立,导致上传处理逻辑完全无法触发。

核心问题2:全局变量依赖与权限判断冗余

原插件函数针对后台场景设计,依赖的全局变量(如$wp_user_avatar、$wpua_force_file_uploader等)在前端用户账户保存钩子中可能未正确初始化;同时,前端普通用户没有publish_posts权限,权限判断分支完全无效,反而增加冗余逻辑。

修正后的代码

// 为表单添加enctype属性支持文件上传
function action_woocommerce_edit_account_form_tag() {
    echo 'enctype="multipart/form-data"';
} 
add_action( 'woocommerce_edit_account_form_tag', 'action_woocommerce_edit_account_form_tag' );

// 在编辑账户表单开头添加头像上传框
function action_woocommerce_edit_account_form_start() {
    ?>
    <p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide">
        <label for="wpua-file"><?php esc_html_e('用户头像', 'woocommerce'); ?></label>
        <input type="file" class="wpua-file" name="wpua-file" id="wpua-file">
    </p>
    <?php
}
add_action( 'woocommerce_edit_account_form_start', 'action_woocommerce_edit_account_form_start' );

// 处理头像上传逻辑
function wpua_process_account_avatar_upload( $user_id ) {
    global $blog_id, $wpdb;
    
    // 仅处理WooCommerce账户提交动作
    if ( ! isset( $_POST['save_account_details'] ) ) {
        return;
    }

    // 处理头像清空逻辑(如果需要可添加对应的清空按钮)
    if ( isset( $_POST['wp-user-avatar'] ) && empty( $_POST['wp-user-avatar'] ) ) {
        // 删除用户所有旧头像附件
        $avatars_query = new WP_Query(array(
            'author'         => $user_id,
            'post_type'      => 'attachment',
            'post_status'    => 'inherit',
            'posts_per_page' => -1,
            'meta_query'     => array(
                array(
                    'key'     => '_wp_attachment_wp_user_avatar',
                    'value'   => $user_id,
                    'compare' => '='
                ),
            ),
        ));

        while( $avatars_query->have_posts() ) {
            $avatars_query->the_post();
            wp_delete_attachment( get_the_ID(), true );
        }
        wp_reset_postdata();

        // 删除用户元数据中的头像记录
        delete_metadata( 'post', null, '_wp_attachment_wp_user_avatar', $user_id, true );
        update_user_meta( $user_id, $wpdb->get_blog_prefix( $blog_id ) . 'user_avatar', '' );
        return;
    }

    // 处理文件上传
    if ( ! empty( $_FILES['wpua-file']['name'] ) && $_FILES['wpua-file']['error'] === UPLOAD_ERR_OK ) {
        $file = $_FILES['wpua-file'];
        $name = sanitize_file_name( $file['name'] );
        $type = sanitize_mime_type( $file['type'] );

        // 验证图片类型
        if ( ! preg_match( '/(jpe?g|gif|png)$/i', $type ) ) {
            wc_add_notice( esc_html__( '仅支持JPG、GIF、PNG格式的图片', 'woocommerce' ), 'error' );
            return;
        }

        // 处理上传
        $upload_result = wp_handle_upload( $file, array(
            'test_form' => false,
            'mimes'     => array(
                'jpg|jpeg|jpe' => 'image/jpeg',
                'gif'          => 'image/gif',
                'png'          => 'image/png'
            )
        ));

        if ( is_wp_error( $upload_result ) ) {
            wc_add_notice( $upload_result->get_error_message(), 'error' );
            return;
        }

        // 获取插件的图片缩放设置
        $wpua_resize_upload = get_option( 'wpua_resize_upload', 1 );
        $wpua_resize_w      = get_option( 'wpua_resize_w', 256 );
        $wpua_resize_h      = get_option( 'wpua_resize_h', 256 );
        $wpua_resize_crop   = get_option( 'wpua_resize_crop', 1 );

        // 缩放图片(如果启用)
        if ( $wpua_resize_upload ) {
            $image_editor = wp_get_image_editor( $upload_result['file'] );
            if ( ! is_wp_error( $image_editor ) ) {
                $image_editor->resize( $wpua_resize_w, $wpua_resize_h, $wpua_resize_crop );
                $image_editor->save( $upload_result['file'] );
            }
        }

        // 构建附件数据
        $name_parts = pathinfo( $name );
        $title      = isset( $name_parts['filename'] ) ? $name_parts['filename'] : $name;
        
        // 尝试读取图片EXIF标题
        $image_meta = wp_read_image_metadata( $upload_result['file'] );
        if ( $image_meta && trim( $image_meta['title'] ) && ! is_numeric( sanitize_title( $image_meta['title'] ) ) ) {
            $title = $image_meta['title'];
        }

        $attachment_data = array(
            'guid'           => $upload_result['url'],
            'post_mime_type' => $type,
            'post_title'     => $title,
            'post_content'   => '',
            'post_status'    => 'inherit',
            'post_author'    => $user_id
        );

        // 插入附件
        $attachment_id = wp_insert_attachment( $attachment_data, $upload_result['file'], 0 );
        if ( is_wp_error( $attachment_id ) ) {
            wc_add_notice( esc_html__( '头像上传失败,请重试', 'woocommerce' ), 'error' );
            return;
        }

        // 生成附件元数据
        wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $upload_result['file'] ) );

        // 删除用户旧头像
        $old_avatars_query = new WP_Query(array(
            'author'         => $user_id,
            'post_type'      => 'attachment',
            'post_status'    => 'inherit',
            'posts_per_page' => -1,
            'post__not_in'   => array( $attachment_id ),
            'meta_query'     => array(
                array(
                    'key'     => '_wp_attachment_wp_user_avatar',
                    'value'   => $user_id,
                    'compare' => '='
                ),
            ),
        ));

        while( $old_avatars_query->have_posts() ) {
            $old_avatars_query->the_post();
            wp_delete_attachment( get_the_ID(), true );
        }
        wp_reset_postdata();

        // 更新附件元数据和用户元数据
        delete_metadata( 'post', null, '_wp_attachment_wp_user_avatar', $user_id, true );
        update_post_meta( $attachment_id, '_wp_attachment_wp_user_avatar', $user_id );
        update_user_meta( $user_id, $wpdb->get_blog_prefix( $blog_id ) . 'user_avatar', $attachment_id );

        wc_add_notice( esc_html__( '头像更新成功', 'woocommerce' ), 'success' );
    }
}
add_action( 'woocommerce_save_account_details', 'wpua_process_account_avatar_upload', 10, 1 );

额外优化点

  • 添加了表单标签和错误提示,提升用户体验
  • 直接从数据库读取插件的缩放设置,避免依赖未初始化的全局变量
  • 优化了旧头像删除逻辑,更精准匹配当前用户的头像附件
  • 添加了文件上传错误处理,及时反馈问题给用户

内容的提问来源于stack exchange,提问作者rk9802710

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 09:17:03