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.
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. |