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
相关产品推荐
相关产品推荐

