函数文档

wp_update_user()

💡 云策文档标注

概述

wp_update_user() 是 WordPress 核心函数,用于更新数据库中的用户信息。它接受用户数据数组或对象,处理密码哈希、邮件通知和 cookie 更新等操作,并返回用户 ID 或 WP_Error。

关键要点

  • 函数参数 $userdata 可以是数组、stdClass 对象或 WP_User 对象,必须包含用户 ID 以指定更新目标。
  • 更新密码时,函数会自动哈希处理,并可能触发密码更改邮件和 cookie 清除(当前用户密码更新时)。
  • 更新邮箱地址时,可能触发邮箱更改邮件,可通过过滤器控制是否发送。
  • 函数内部调用 wp_insert_user() 执行实际更新,并整合了用户元数据。
  • 返回值为更新后的用户 ID(整数)或 WP_Error 对象,便于错误处理。
  • 提供了多个钩子(如 wp_update_user、send_password_change_email)用于自定义行为。

代码示例

$user_data = wp_update_user( array( 'ID' => $user_id, 'user_url' => $website ) );

if ( is_wp_error( $user_data ) ) {
    // 处理错误
    echo 'Error.';
} else {
    // 成功
    echo 'User profile updated.';
}

注意事项

  • 更新密码或邮箱时会自动发送通知邮件,可通过过滤器 send_password_change_email 和 send_email_change_email 禁用。
  • 无法直接更新 user_login 字段,WordPress 限制修改用户名。
  • 使用前需确保用户 ID 有效,否则返回 WP_Error。
  • 函数会清理用户缓存,确保数据一致性。

📄 原文内容

Updates a user in the database.

Description

It is possible to update a user’s password by specifying the ‘user_pass’ value in the $userdata parameter array.

If current user’s password is being updated, then the cookies will be cleared.

See also

Parameters

$userdataarray|object|WP_Userrequired
An array of user data or a user object of type stdClass or WP_User.

Return

int|WP_Error The updated user’s ID or a WP_Error object if the user could not be updated.

Source

function wp_update_user( $userdata ) {
	if ( $userdata instanceof stdClass ) {
		$userdata = get_object_vars( $userdata );
	} elseif ( $userdata instanceof WP_User ) {
		$userdata = $userdata->to_array();
	}

	$userdata_raw = $userdata;

	$user_id = isset( $userdata['ID'] ) ? (int) $userdata['ID'] : 0;
	if ( ! $user_id ) {
		return new WP_Error( 'invalid_user_id', __( 'Invalid user ID.' ) );
	}

	// First, get all of the original fields.
	$user_obj = get_userdata( $user_id );
	if ( ! $user_obj ) {
		return new WP_Error( 'invalid_user_id', __( 'Invalid user ID.' ) );
	}

	$user = $user_obj->to_array();

	// Add additional custom fields.
	foreach ( _get_additional_user_keys( $user_obj ) as $key ) {
		$user[ $key ] = get_user_meta( $user_id, $key, true );
	}

	// Escape data pulled from DB.
	$user = add_magic_quotes( $user );

	if ( ! empty( $userdata['user_pass'] ) && $userdata['user_pass'] !== $user_obj->user_pass ) {
		// If password is changing, hash it now.
		$plaintext_pass        = $userdata['user_pass'];
		$userdata['user_pass'] = wp_hash_password( $userdata['user_pass'] );

		/** This action is documented in wp-includes/pluggable.php */
		do_action( 'wp_set_password', $plaintext_pass, $user_id, $user_obj );

		/**
		 * Filters whether to send the password change email.
		 *
		 * @since 4.3.0
		 *
		 * @see wp_insert_user() For `$user` and `$userdata` fields.
		 *
		 * @param bool  $send     Whether to send the email.
		 * @param array $user     The original user array.
		 * @param array $userdata The updated user array.
		 */
		$send_password_change_email = apply_filters( 'send_password_change_email', true, $user, $userdata );
	}

	if ( isset( $userdata['user_email'] ) && $user['user_email'] !== $userdata['user_email'] ) {
		/**
		 * Filters whether to send the email change email.
		 *
		 * @since 4.3.0
		 *
		 * @see wp_insert_user() For `$user` and `$userdata` fields.
		 *
		 * @param bool  $send     Whether to send the email.
		 * @param array $user     The original user array.
		 * @param array $userdata The updated user array.
		 */
		$send_email_change_email = apply_filters( 'send_email_change_email', true, $user, $userdata );
	}

	clean_user_cache( $user_obj );

	// Merge old and new fields with new fields overwriting old ones.
	$userdata = array_merge( $user, $userdata );
	$user_id  = wp_insert_user( $userdata );

	if ( is_wp_error( $user_id ) ) {
		return $user_id;
	}

	$blog_name = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );

	$switched_locale = false;
	if ( ! empty( $send_password_change_email ) || ! empty( $send_email_change_email ) ) {
		$switched_locale = switch_to_user_locale( $user_id );
	}

	if ( ! empty( $send_password_change_email ) ) {
		/* translators: Do not translate USERNAME, ADMIN_EMAIL, EMAIL, SITENAME, SITEURL: those are placeholders. */
		$pass_change_text = __(
			'Hi ###USERNAME###,

This notice confirms that your password was changed on ###SITENAME###.

If you did not change your password, please contact the Site Administrator at
###ADMIN_EMAIL###

This email has been sent to ###EMAIL###

Regards,
All at ###SITENAME###
###SITEURL###'
		);

		$pass_change_email = array(
			'to'      => $user['user_email'],
			/* translators: Password change notification email subject. %s: Site title. */
			'subject' => __( '[%s] Password Changed' ),
			'message' => $pass_change_text,
			'headers' => '',
		);

		/**
		 * Filters the contents of the email sent when the user's password is changed.
		 *
		 * @since 4.3.0
		 *
		 * @param array $pass_change_email {
		 *     Used to build wp_mail().
		 *
		 *     @type string $to      The intended recipients. Add emails in a comma separated string.
		 *     @type string $subject The subject of the email.
		 *     @type string $message The content of the email.
		 *         The following strings have a special meaning and will get replaced dynamically:
		 *          - `###USERNAME###`    The current user's username.
		 *          - `###ADMIN_EMAIL###` The admin email in case this was unexpected.
		 *          - `###EMAIL###`       The user's email address.
		 *          - `###SITENAME###`    The name of the site.
		 *          - `###SITEURL###`     The URL to the site.
		 *     @type string $headers Headers. Add headers in a newline (rn) separated string.
		 * }
		 * @param array $user     The original user array.
		 * @param array $userdata The updated user array.
		 */
		$pass_change_email = apply_filters( 'password_change_email', $pass_change_email, $user, $userdata );

		$pass_change_email['message'] = str_replace( '###USERNAME###', $user['user_login'], $pass_change_email['message'] );
		$pass_change_email['message'] = str_replace( '###ADMIN_EMAIL###', get_option( 'admin_email' ), $pass_change_email['message'] );
		$pass_change_email['message'] = str_replace( '###EMAIL###', $user['user_email'], $pass_change_email['message'] );
		$pass_change_email['message'] = str_replace( '###SITENAME###', $blog_name, $pass_change_email['message'] );
		$pass_change_email['message'] = str_replace( '###SITEURL###', home_url(), $pass_change_email['message'] );

		wp_mail( $pass_change_email['to'], sprintf( $pass_change_email['subject'], $blog_name ), $pass_change_email['message'], $pass_change_email['headers'] );
	}

	if ( ! empty( $send_email_change_email ) ) {
		/* translators: Do not translate USERNAME, ADMIN_EMAIL, NEW_EMAIL, EMAIL, SITENAME, SITEURL: those are placeholders. */
		$email_change_text = __(
			'Hi ###USERNAME###,

This notice confirms that your email address on ###SITENAME### was changed to ###NEW_EMAIL###.

If you did not change your email, please contact the Site Administrator at
###ADMIN_EMAIL###

This email has been sent to ###EMAIL###

Regards,
All at ###SITENAME###
###SITEURL###'
		);

		$email_change_email = array(
			'to'      => $user['user_email'],
			/* translators: Email change notification email subject. %s: Site title. */
			'subject' => __( '[%s] Email Changed' ),
			'message' => $email_change_text,
			'headers' => '',
		);

		/**
		 * Filters the contents of the email sent when the user's email is changed.
		 *
		 * @since 4.3.0
		 *
		 * @param array $email_change_email {
		 *     Used to build wp_mail().
		 *
		 *     @type string $to      The intended recipients.
		 *     @type string $subject The subject of the email.
		 *     @type string $message The content of the email.
		 *         The following strings have a special meaning and will get replaced dynamically:
		 *          - `###USERNAME###`    The current user's username.
		 *          - `###ADMIN_EMAIL###` The admin email in case this was unexpected.
		 *          - `###NEW_EMAIL###`   The new email address.
		 *          - `###EMAIL###`       The old email address.
		 *          - `###SITENAME###`    The name of the site.
		 *          - `###SITEURL###`     The URL to the site.
		 *     @type string $headers Headers.
		 * }
		 * @param array $user     The original user array.
		 * @param array $userdata The updated user array.
		 */
		$email_change_email = apply_filters( 'email_change_email', $email_change_email, $user, $userdata );

		$email_change_email['message'] = str_replace( '###USERNAME###', $user['user_login'], $email_change_email['message'] );
		$email_change_email['message'] = str_replace( '###ADMIN_EMAIL###', get_option( 'admin_email' ), $email_change_email['message'] );
		$email_change_email['message'] = str_replace( '###NEW_EMAIL###', $userdata['user_email'], $email_change_email['message'] );
		$email_change_email['message'] = str_replace( '###EMAIL###', $user['user_email'], $email_change_email['message'] );
		$email_change_email['message'] = str_replace( '###SITENAME###', $blog_name, $email_change_email['message'] );
		$email_change_email['message'] = str_replace( '###SITEURL###', home_url(), $email_change_email['message'] );

		wp_mail( $email_change_email['to'], sprintf( $email_change_email['subject'], $blog_name ), $email_change_email['message'], $email_change_email['headers'] );
	}

	if ( $switched_locale ) {
		restore_previous_locale();
	}

	// Update the cookies if the password changed.
	$current_user = wp_get_current_user();
	if ( $current_user->ID === $user_id ) {
		if ( isset( $plaintext_pass ) ) {
			/*
			 * Here we calculate the expiration length of the current auth cookie and compare it to the default expiration.
			 * If it's greater than this, then we know the user checked 'Remember Me' when they logged in.
			 */
			$logged_in_cookie = wp_parse_auth_cookie( '', 'logged_in' );
			/** This filter is documented in wp-includes/pluggable.php */
			$default_cookie_life = apply_filters( 'auth_cookie_expiration', ( 2 * DAY_IN_SECONDS ), $user_id, false );

			wp_clear_auth_cookie();

			$remember = false;
			$token    = '';

			if ( false !== $logged_in_cookie ) {
				$token = $logged_in_cookie['token'];
			}

			if ( false !== $logged_in_cookie && ( (int) $logged_in_cookie['expiration'] - time() ) > $default_cookie_life ) {
				$remember = true;
			}

			wp_set_auth_cookie( $user_id, $remember, '', $token );
		}
	}

	/**
	 * Fires after the user has been updated and emails have been sent.
	 *
	 * @since 6.3.0
	 *
	 * @param int   $user_id      The ID of the user that was just updated.
	 * @param array $userdata     The array of user data that was updated.
	 * @param array $userdata_raw The unedited array of user data that was updated.
	 */
	do_action( 'wp_update_user', $user_id, $userdata, $userdata_raw );

	return $user_id;
}

Hooks

apply_filters( ‘auth_cookie_expiration’, int $length, int $user_id, bool $remember )

Filters the duration of the authentication cookie expiration period.

apply_filters( ’email_change_email’, array $email_change_email, array $user, array $userdata )

Filters the contents of the email sent when the user’s email is changed.

apply_filters( ‘password_change_email’, array $pass_change_email, array $user, array $userdata )

Filters the contents of the email sent when the user’s password is changed.

apply_filters( ‘send_email_change_email’, bool $send, array $user, array $userdata )

Filters whether to send the email change email.

apply_filters( ‘send_password_change_email’, bool $send, array $user, array $userdata )

Filters whether to send the password change email.

do_action( ‘wp_set_password’, string $password, int $user_id, WP_User $old_user_data )

Fires after the user password is set.

do_action( ‘wp_update_user’, int $user_id, array $userdata, array $userdata_raw )

Fires after the user has been updated and emails have been sent.

Changelog

Version Description
2.0.0 Introduced.

User Contributed Notes

  1. Skip to note 6 content

    “If current user’s password is being updated, then the cookies will be cleared.” AND AN EMAIL WILL BE SEND !!!
    It sent an email to 50 users !!! Be more explicit !

  2. Skip to note 8 content

    An example showing how to update a user_meta field (for example, ‘wpdocs_free_offers_left’) with a WP_User object.

    $user = wp_get_current_user();
    
    $free_offers = $user->free_offers_left;
    update_user_meta( $user->ID, 'wpdocs_free_offers_left', $free_offers-- );
    
    $update = wp_update_user( $user );
    
    if ( is_int( $update ) ) {
      // Success
      echo "Update done";
    } else { // is WP_error
      echo "Update failed";
    }