函数文档

update_metadata()

💡 云策文档标注

概述

update_metadata() 是 WordPress 核心函数,用于更新指定对象的元数据。如果元数据键不存在,则会自动添加。该函数支持多种对象类型,如 post、user、term 等,并包含钩子以允许开发者干预更新过程。

关键要点

  • 函数签名:update_metadata( $meta_type, $object_id, $meta_key, $meta_value, $prev_value = '' )
  • 参数:$meta_type(对象类型,如 'post'、'user')、$object_id(对象ID)、$meta_key(元数据键)、$meta_value(元数据值,非标量需可序列化)、$prev_value(可选,用于检查的先前值)
  • 返回值:新元数据字段ID(如果添加)、true(成功更新)、false(失败或值未变)
  • 历史原因:输入时元数据键和值需“转义斜杠”(slashed),函数内部会处理 wp_unslash
  • 钩子:包括 update_{$meta_type}_metadata(短路径过滤)、update_{$meta_type}_meta(更新前动作)、updated_{$meta_type}_meta(更新后动作)等
  • 相关函数:如 get_metadata_raw()、add_metadata()、sanitize_meta(),用于辅助元数据操作

代码示例

// 更新文章的元数据,键为 'my_custom_field',值为 'new_value'
$result = update_metadata( 'post', 123, 'my_custom_field', 'new_value' );
if ( $result ) {
    echo '元数据更新成功';
} else {
    echo '更新失败或值未变';
}

注意事项

  • 确保 $meta_type 有效且对应元数据表存在,否则函数返回 false
  • 非标量 $meta_value(如数组、对象)必须可序列化,函数会使用 maybe_serialize() 处理
  • 使用 $prev_value 可精确更新特定值的元数据条目,避免意外覆盖
  • 更新后会自动清除相关缓存(wp_cache_delete),但开发者需注意性能影响

📄 原文内容

Updates metadata for the specified object. If no value already exists for the specified object ID and metadata key, the metadata will be added.

Description

For historical reasons both the meta key and the meta value are expected to be “slashed” (slashes escaped) on input.

Parameters

$meta_typestringrequired
Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term', 'user', or any other object type with an associated meta table.
$object_idintrequired
ID of the object metadata is for.
$meta_keystringrequired
Metadata key.
$meta_valuemixedrequired
Metadata value. Must be serializable if non-scalar.
$prev_valuemixedoptional
Previous value to check before updating.
If specified, only update existing metadata entries with this value. Otherwise, update all entries. Default empty string.

Return

int|bool The new meta field ID if a field with the given key didn’t exist and was therefore added, true on successful update, false on failure or if the value passed to the function is the same as the one that is already in the database.

Source

function update_metadata( $meta_type, $object_id, $meta_key, $meta_value, $prev_value = '' ) {
	global $wpdb;

	if ( ! $meta_type || ! $meta_key || ! is_numeric( $object_id ) ) {
		return false;
	}

	$object_id = absint( $object_id );
	if ( ! $object_id ) {
		return false;
	}

	$table = _get_meta_table( $meta_type );
	if ( ! $table ) {
		return false;
	}

	$meta_subtype = get_object_subtype( $meta_type, $object_id );

	$column    = sanitize_key( $meta_type . '_id' );
	$id_column = ( 'user' === $meta_type ) ? 'umeta_id' : 'meta_id';

	// expected_slashed ($meta_key)
	$raw_meta_key = $meta_key;
	$meta_key     = wp_unslash( $meta_key );
	$passed_value = $meta_value;
	$meta_value   = wp_unslash( $meta_value );
	$meta_value   = sanitize_meta( $meta_key, $meta_value, $meta_type, $meta_subtype );

	/**
	 * Short-circuits updating metadata of a specific type.
	 *
	 * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
	 * (blog, post, comment, term, user, or any other type with an associated meta table).
	 * Returning a non-null value will effectively short-circuit the function.
	 *
	 * Possible hook names include:
	 *
	 *  - `update_blog_metadata`
	 *  - `update_post_metadata`
	 *  - `update_comment_metadata`
	 *  - `update_term_metadata`
	 *  - `update_user_metadata`
	 *
	 * @since 3.1.0
	 *
	 * @param null|bool $check      Whether to allow updating metadata for the given type.
	 * @param int       $object_id  ID of the object metadata is for.
	 * @param string    $meta_key   Metadata key.
	 * @param mixed     $meta_value Metadata value. Must be serializable if non-scalar.
	 * @param mixed     $prev_value Optional. Previous value to check before updating.
	 *                              If specified, only update existing metadata entries with
	 *                              this value. Otherwise, update all entries.
	 */
	$check = apply_filters( "update_{$meta_type}_metadata", null, $object_id, $meta_key, $meta_value, $prev_value );
	if ( null !== $check ) {
		return (bool) $check;
	}

	// Compare existing value to new value if no prev value given and the key exists only once.
	if ( empty( $prev_value ) ) {
		$old_value = get_metadata_raw( $meta_type, $object_id, $meta_key );
		if ( is_countable( $old_value ) && count( $old_value ) === 1 ) {
			if ( $old_value[0] === $meta_value ) {
				return false;
			}
		}
	}

	$meta_ids = $wpdb->get_col( $wpdb->prepare( "SELECT $id_column FROM $table WHERE meta_key = %s AND $column = %d", $meta_key, $object_id ) );
	if ( empty( $meta_ids ) ) {
		return add_metadata( $meta_type, $object_id, $raw_meta_key, $passed_value );
	}

	$_meta_value = $meta_value;
	$meta_value  = maybe_serialize( $meta_value );

	$data  = compact( 'meta_value' );
	$where = array(
		$column    => $object_id,
		'meta_key' => $meta_key,
	);

	if ( ! empty( $prev_value ) ) {
		$prev_value          = maybe_serialize( $prev_value );
		$where['meta_value'] = $prev_value;
	}

	foreach ( $meta_ids as $meta_id ) {
		/**
		 * Fires immediately before updating metadata of a specific type.
		 *
		 * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
		 * (blog, post, comment, term, user, or any other type with an associated meta table).
		 *
		 * Possible hook names include:
		 *
		 *  - `update_blog_meta`
		 *  - `update_post_meta`
		 *  - `update_comment_meta`
		 *  - `update_term_meta`
		 *  - `update_user_meta`
		 *
		 * @since 2.9.0
		 *
		 * @param int    $meta_id     ID of the metadata entry to update.
		 * @param int    $object_id   ID of the object metadata is for.
		 * @param string $meta_key    Metadata key.
		 * @param mixed  $_meta_value Metadata value.
		 */
		do_action( "update_{$meta_type}_meta", $meta_id, $object_id, $meta_key, $_meta_value );

		if ( 'post' === $meta_type ) {
			/**
			 * Fires immediately before updating a post's metadata.
			 *
			 * @since 2.9.0
			 *
			 * @param int    $meta_id    ID of metadata entry to update.
			 * @param int    $object_id  Post ID.
			 * @param string $meta_key   Metadata key.
			 * @param mixed  $meta_value Metadata value. This will be a PHP-serialized string representation of the value
			 *                           if the value is an array, an object, or itself a PHP-serialized string.
			 */
			do_action( 'update_postmeta', $meta_id, $object_id, $meta_key, $meta_value );
		}
	}

	$result = $wpdb->update( $table, $data, $where );
	if ( ! $result ) {
		return false;
	}

	wp_cache_delete( $object_id, $meta_type . '_meta' );

	foreach ( $meta_ids as $meta_id ) {
		/**
		 * Fires immediately after updating metadata of a specific type.
		 *
		 * The dynamic portion of the hook name, `$meta_type`, refers to the meta object type
		 * (blog, post, comment, term, user, or any other type with an associated meta table).
		 *
		 * Possible hook names include:
		 *
		 *  - `updated_blog_meta`
		 *  - `updated_post_meta`
		 *  - `updated_comment_meta`
		 *  - `updated_term_meta`
		 *  - `updated_user_meta`
		 *
		 * @since 2.9.0
		 *
		 * @param int    $meta_id     ID of updated metadata entry.
		 * @param int    $object_id   ID of the object metadata is for.
		 * @param string $meta_key    Metadata key.
		 * @param mixed  $_meta_value Metadata value.
		 */
		do_action( "updated_{$meta_type}_meta", $meta_id, $object_id, $meta_key, $_meta_value );

		if ( 'post' === $meta_type ) {
			/**
			 * Fires immediately after updating a post's metadata.
			 *
			 * @since 2.9.0
			 *
			 * @param int    $meta_id    ID of updated metadata entry.
			 * @param int    $object_id  Post ID.
			 * @param string $meta_key   Metadata key.
			 * @param mixed  $meta_value Metadata value. This will be a PHP-serialized string representation of the value
			 *                           if the value is an array, an object, or itself a PHP-serialized string.
			 */
			do_action( 'updated_postmeta', $meta_id, $object_id, $meta_key, $meta_value );
		}
	}

	return true;
}

Hooks

do_action( ‘updated_postmeta’, int $meta_id, int $object_id, string $meta_key, mixed $meta_value )

Fires immediately after updating a post’s metadata.

do_action( “updated_{$meta_type}_meta”, int $meta_id, int $object_id, string $meta_key, mixed $_meta_value )

Fires immediately after updating metadata of a specific type.

do_action( ‘update_postmeta’, int $meta_id, int $object_id, string $meta_key, mixed $meta_value )

Fires immediately before updating a post’s metadata.

do_action( “update_{$meta_type}_meta”, int $meta_id, int $object_id, string $meta_key, mixed $_meta_value )

Fires immediately before updating metadata of a specific type.

apply_filters( “update_{$meta_type}_metadata”, null|bool $check, int $object_id, string $meta_key, mixed $meta_value, mixed $prev_value )

Short-circuits updating metadata of a specific type.

Changelog

Version Description
2.9.0 Introduced.