WordPress profile_update钩子无法获取更新后用户角色问题求助
问题:WordPress用户信息同步接口无法获取更新后的角色
背景代码
我编写了一段代码,用于在管理员或用户从后台修改用户信息时,将信息同步至指定接口:
// Función para enviar la actualización de perfil de usuario al endpoint function send_profile_update_to_endpoint($user_id, $old_user_data = null, $userdata = null) { // Eliminar la entrada de caché correspondiente a los datos del usuario wp_cache_delete($user_id, 'users'); // Obtener los datos del usuario modificado $user = get_userdata($user_id); $token = '-----------'; // Token de autorización // Verificar si el usuario tiene el rol "VIP" para establecer el valor de "partner" $partner = in_array('vip', (array) $user->roles); // Construir el array de datos del usuario para enviar en el body de la solicitud $user_data = array( 'name' => $user->first_name, 'surname' => $user->last_name, 'email' => $user->user_email, 'password' => base64_encode($user->user_pass), 'passwordMD5' => $user->user_pass, 'original_email' => $user->user_email, 'username' => $user->user_login, 'business_name' => '', 'country' => '', 'zip_code' => '', 'phone' => '', 'newsletter' => '', 'partner' => $partner ? true : '', 'member' => '' ); $body = array('users' => array($user_data)); // Construir el cuerpo de la solicitud // Configurar los encabezados de la solicitud $headers = array( 'Authorization' => 'Bearer ' . $token, 'X-Requested-With' => 'XMLHttpRequest', 'Content-Type' => 'application/json' ); // Realizar la solicitud HTTP POST $response = wp_remote_post('https://test.com/api/users/sync', array( 'method' => 'POST', 'headers' => $headers, 'body' => json_encode($body) )); // Verificar la respuesta de la solicitud if (is_wp_error($response)) { // Ocurrió un error al realizar la solicitud error_log('Error al enviar la actualización de perfil al endpoint: ' . $response->get_error_message()); } else { $response_code = wp_remote_retrieve_response_code($response); $response_body = wp_remote_retrieve_body($response); // Verificar el código de respuesta y registrar el resultado en los registros if ($response_code === 200) { // La solicitud fue exitosa error_log('Actualización de perfil enviada al endpoint correctamente. Respuesta: ' . $response_body); } else { // La solicitud no tuvo éxito error_log('Error al enviar la actualización de perfil al endpoint. Código de respuesta: ' . $response_code); } } }
当前问题
修改用户基础信息(如姓名)时接口能收到新数据,但修改用户角色时,钩子无法检测到更新后的角色,仍发送旧角色信息。例如将用户William的角色从super改为vip时,姓名更新为Alfred能被检测到,但角色仍为super。
推测原因
WordPress后台修改用户信息(含角色)时,profile_update钩子在wp_update_user正式更新角色前触发,导致代码获取旧角色。
已尝试的钩子(均无效)
- 后台用户资料更新钩子:
add_action('profile_update', 'send_profile_update_to_endpoint', 10, 3); - 角色变更钩子:
add_action('set_user_role', 'send_profile_update_to_endpoint_roles', 10, 3);(已注释) - 前台个人资料更新钩子:
add_action('personal_options_update', 'send_profile_update_to_endpoint', 10, 3); - WooCommerce账户更新钩子:
add_action('woocommerce_update_customer', 'send_profile_update_to_endpoint', 10, 1);
额外问题
$userdata返回内容不含角色信息,与WordPress官方文档描述不符,返回内容如下:
( [ID] => 289 [user_login] => pruebesita 23 [user_pass] => $P$BA8J63LF.1W5iH1gYPqhROT6s5Sb4y0 [user_nicename] => pruebesita-23 [user_email] => nose+34@gmail.com [user_url] => [user_registered] => 2023-06-08 16:08:14 [user_activation_key] => 1686240496:$P$BfcKS1xXubceLVaE8fFjPXCVaMnJmO0 [user_status] => 0 [display_name] => manu eee [first_name] => Manuel P [last_name] => P M [nickname] => vaale [description] => [rich_editing] => true [syntax_highlighting] => true [comment_shortcuts] => [admin_color] => fresh [use_ssl] => 0 [show_admin_bar_front] => true [locale] => [facebook] => [instagram] => [linkedin] => [myspace] => [pinterest] => [soundcloud] => [tumblr] => [twitter] => [youtube] => [wikipedia] => )
需求
实现用户基础信息或角色变更时,均能将最新信息同步至指定接口。
解决方案
核心思路
WordPress中角色更新与用户基础信息更新的逻辑分离:profile_update触发时角色可能未完成写入,需通过提高钩子优先级确保数据完全更新,同时用set_user_role钩子单独处理角色变更场景。
优化后代码
// 调整优先级为99,确保用户数据(含角色)完全写入后触发 add_action('profile_update', 'send_profile_update_to_endpoint', 99, 3); // 单独处理角色变更事件 add_action('set_user_role', 'send_profile_update_on_role_change', 10, 3); function send_profile_update_to_endpoint($user_id, $old_user_data = null, $userdata = null) { // 强制清理用户主数据和元数据缓存,避免读取旧数据 wp_cache_delete($user_id, 'users'); wp_cache_delete($user_id, 'user_meta'); $user = get_userdata($user_id); if (!$user) { error_log('无法获取用户ID: ' . $user_id . '的最新数据'); return; } $token = '-----------'; // 替换为实际授权Token $partner = in_array('vip', (array) $user->roles); $user_data = array( 'name' => $user->first_name, 'surname' => $user->last_name, 'email' => $user->user_email, 'password' => base64_encode($user->user_pass), 'passwordMD5' => $user->user_pass, 'original_email' => $user->user_email, 'username' => $user->user_login, 'business_name' => '', 'country' => '', 'zip_code' => '', 'phone' => '', 'newsletter' => '', 'partner' => $partner ? true : '', 'member' => '' ); $body = array('users' => array($user_data)); $headers = array( 'Authorization' => 'Bearer ' . $token, 'X-Requested-With' => 'XMLHttpRequest', 'Content-Type' => 'application/json' ); $response = wp_remote_post('https://test.com/api/users/sync', array( 'method' => 'POST', 'headers' => $headers, 'body' => json_encode($body) )); if (is_wp_error($response)) { error_log('同步用户信息失败: ' . $response->get_error_message()); } else { $response_code = wp_remote_retrieve_response_code($response); $response_body = wp_remote_retrieve_body($response); if ($response_code === 200) { error_log('用户信息同步成功,响应: ' . $response_body); } else { error_log('用户信息同步失败,响应码: ' . $response_code . ', 响应内容: ' . $response_body); } } } // 角色变更时触发同步 function send_profile_update_on_role_change($user_id, $role, $old_roles) { send_profile_update_to_endpoint($user_id); }
关键优化点
- 提高
profile_update优先级:从默认10改为99,确保数据库中用户数据(包括角色)完全写入后再执行同步。 - 扩展缓存清理:除了
users缓存,额外清理user_meta缓存,彻底避免读取旧角色数据。 - 单独处理角色变更:利用
set_user_role钩子,角色变更时直接触发同步,覆盖纯角色修改的场景。 - 增加用户存在性检查:避免因用户数据未正确加载导致的同步错误。
补充说明
$userdata不含角色是正常现象:WordPress角色存储在用户元数据中,而非用户主表,官方文档描述存在模糊,通过get_userdata获取完整数据是正确方式。- WooCommerce场景可保留
woocommerce_update_customer钩子,同样建议将优先级调整为99以确保数据更新完成。
内容的提问来源于stack exchange,提问作者Manuel Prieto macías
相关产品推荐
相关产品推荐

