set_transient()
云策文档标注
概述
set_transient() 函数用于设置或更新瞬态(transient)的值,支持设置过期时间。开发者无需手动序列化值,函数会自动处理序列化,并返回布尔值表示操作是否成功。
关键要点
- 参数:$transient(瞬态名称,不超过172字符,无需SQL转义),$value(瞬态值,非标量需可序列化),$expiration(过期时间,秒为单位,默认0表示永不过期)。
- 返回:布尔值,true表示设置成功,false表示失败。
- 名称限制:瞬态名称在数据库中受wp_options表的option_name字段限制(191字符),若未启用memcached,前缀“_transient_”或“_transient_timeout_”会添加到名称前,总长不超过172字符以避免静默失败。
- 过期行为:永不过期的瞬态会自动加载(autoload),而有过期时间的则不会,影响页面性能,需根据需求选择。
- 内部处理:函数使用过滤器(如pre_set_transient_{$transient}和expiration_of_transient_{$transient})和动作钩子(如set_transient_{$transient}),并基于wp_using_ext_object_cache()判断使用外部对象缓存或数据库存储。
- 版本变化:WordPress 4.4后名称长度限制从45增至172字符,数据库限制从64增至191字符。
代码示例
// 设置一个过期时间为一天的瞬态,存储最新5篇文章的查询结果
$args = array(
'post_type' => 'post',
'posts_per_page' => 5,
'orderby' => 'date',
'order' => 'DESC'
);
$latest_post = new WP_Query( $args );
set_transient( 'latest_5_posts', $latest_post, DAY_IN_SECONDS );注意事项
- 更新现有瞬态时,若不提供$expiration参数,会保持原有过期时间,而非重置或设为永不过期。
- 避免直接缓存WP_Query对象,可能导致性能问题,建议存储post ID数组。
- 使用持久对象缓存时,瞬态存储在缓存中而非wp_options表,避免直接操作数据库。
- 瞬态过期时间以UNIX时间戳形式存储在_transient_timeout_{$transient}选项中。
- WP_CACHE常量无需设为true即可使用瞬态功能。
原文内容
Sets/updates the value of a transient.
Description
You do not need to serialize values. If the value needs to be serialized, then it will be serialized before it is set.
Parameters
$transientstringrequired-
Transient name. Expected to not be SQL-escaped.
Must be 172 characters or fewer in length. $valuemixedrequired-
Transient value. Must be serializable if non-scalar.
Expected to not be SQL-escaped. $expirationintoptional-
Time until expiration in seconds. Default 0 (no expiration).
Source
function set_transient( $transient, $value, $expiration = 0 ) {
$expiration = (int) $expiration;
/**
* Filters a specific transient before its value is set.
*
* The dynamic portion of the hook name, `$transient`, refers to the transient name.
*
* @since 3.0.0
* @since 4.2.0 The `$expiration` parameter was added.
* @since 4.4.0 The `$transient` parameter was added.
*
* @param mixed $value New value of transient.
* @param int $expiration Time until expiration in seconds.
* @param string $transient Transient name.
*/
$value = apply_filters( "pre_set_transient_{$transient}", $value, $expiration, $transient );
/**
* Filters the expiration for a transient before its value is set.
*
* The dynamic portion of the hook name, `$transient`, refers to the transient name.
*
* @since 4.4.0
*
* @param int $expiration Time until expiration in seconds. Use 0 for no expiration.
* @param mixed $value New value of transient.
* @param string $transient Transient name.
*/
$expiration = apply_filters( "expiration_of_transient_{$transient}", $expiration, $value, $transient );
if ( wp_using_ext_object_cache() || wp_installing() ) {
$result = wp_cache_set( $transient, $value, 'transient', $expiration );
} else {
$transient_timeout = '_transient_timeout_' . $transient;
$transient_option = '_transient_' . $transient;
wp_prime_option_caches( array( $transient_option, $transient_timeout ) );
if ( false === get_option( $transient_option ) ) {
$autoload = true;
if ( $expiration ) {
$autoload = false;
add_option( $transient_timeout, time() + $expiration, '', false );
}
$result = add_option( $transient_option, $value, '', $autoload );
} else {
/*
* If expiration is requested, but the transient has no timeout option,
* delete, then re-create transient rather than update.
*/
$update = true;
if ( $expiration ) {
if ( false === get_option( $transient_timeout ) ) {
delete_option( $transient_option );
add_option( $transient_timeout, time() + $expiration, '', false );
$result = add_option( $transient_option, $value, '', false );
$update = false;
} else {
update_option( $transient_timeout, time() + $expiration );
}
}
if ( $update ) {
$result = update_option( $transient_option, $value );
}
}
}
if ( $result ) {
/**
* Fires after the value for a specific transient has been set.
*
* The dynamic portion of the hook name, `$transient`, refers to the transient name.
*
* @since 3.0.0
* @since 3.6.0 The `$value` and `$expiration` parameters were added.
* @since 4.4.0 The `$transient` parameter was added.
*
* @param mixed $value Transient value.
* @param int $expiration Time until expiration in seconds.
* @param string $transient The name of the transient.
*/
do_action( "set_transient_{$transient}", $value, $expiration, $transient );
/**
* Fires after the value for a transient has been set.
*
* @since 6.8.0
*
* @param string $transient The name of the transient.
* @param mixed $value Transient value.
* @param int $expiration Time until expiration in seconds.
*/
do_action( 'set_transient', $transient, $value, $expiration );
/**
* Fires after the transient is set.
*
* @since 3.0.0
* @since 3.6.0 The `$value` and `$expiration` parameters were added.
* @deprecated 6.8.0 Use 'set_transient' instead.
*
* @param string $transient The name of the transient.
* @param mixed $value Transient value.
* @param int $expiration Time until expiration in seconds.
*/
do_action_deprecated( 'setted_transient', array( $transient, $value, $expiration ), '6.8.0', 'set_transient' );
}
return $result;
}
Hooks
- apply_filters( “expiration_of_transient_{$transient}”, int $expiration, mixed $value, string $transient )
-
Filters the expiration for a transient before its value is set.
- apply_filters( “pre_set_transient_{$transient}”, mixed $value, int $expiration, string $transient )
-
Filters a specific transient before its value is set.
- do_action_deprecated( ‘setted_transient’, string $transient, mixed $value, int $expiration )
-
Fires after the transient is set.
- do_action( ‘set_transient’, string $transient, mixed $value, int $expiration )
-
Fires after the value for a transient has been set.
- do_action( “set_transient_{$transient}”, mixed $value, int $expiration, string $transient )
-
Fires after the value for a specific transient has been set.
Changelog
| Version | Description |
|---|---|
| 2.8.0 | Introduced. |
Skip to note 7 content
crstauf
Unless you’re using an external object cache, when using
set_transient()to update an existing transient that has an existing expiration, not providing an expiration value will maintain the existing expiration.For example:
$initial = time(); set_transient( 'foo', 'bar', 300 ); sleep( 10 ); $update = time(); set_transient( 'foo', 'barbar' );In this case, the expiration would remain as
$initial + 300(and not change to$update + 300, or never expires), because the secondset_transient()call does not include an$expirationvalue (only the transient’s value is updated).Be careful though, because you may unintentionally set a transient to never expire, if the transient expired before the second call (without the
$expirationparameter) is made.Skip to note 8 content
Nicola Mustone
This example shows how to set a transient with the latest five blog posts. It expires after one day.
It uses time constants to set the expiration time.
// Set the arguments for the custom query $args = array( 'post_type' => 'post', 'posts_per_page' => 5, 'orderby' => 'date', 'order' => 'DESC' ); $latest_post = new WP_Query( $args ); // Save the results in a transient named latest_5_posts set_transient( 'latest_5_posts', $latest_post, DAY_IN_SECONDS );To know more about how to get posts and custom post type items read the documentation of WP_Query.
WP_Queryin a transient like this will cause a performance hit. This is because WP_Query bulk fetches the post objects, their terms, and their taxonomies in advance into WP_Cache to avoid database queries. But when the transient is used and WP_Query is recreated, none of that has happened. As a result WordPress has to pause constantly to make small database queries to fetch the post meta and terms that were previously cached. Instead store the result as an array of post IDs. Post IDs are super fast to fetch and may even be in WP_Cache already. After all the most expensive part of the query is figuring out which post IDs match the desired results.Skip to note 9 content
Codex
Saving the $special_query_results object for 12 hours
set_transient( 'special_query_results', $special_query_results, 12 * HOUR_IN_SECONDS );Skip to note 10 content
Lovekesh Kumar
WordPress saves the transients expiration time in the form of a UNIX timestamp. When you look for the
option name in the options table of WordPress, it will look like 1636453079 which is in UNIX timestamp not in seconds.
See the code on GitHub
Skip to note 11 content
OllieJones
Beware! When you use a persistent object cache plugin, WordPress core stores transients in that persistent object cache, not in the wp_options table.
Avoid the mistake of setting a transient by using the update_option API, or by writing something directly into the options table.
Skip to note 12 content
Vishnu Gopal
Note that
WP_CACHEhas to be true inwp-config.phpfor transients to work:define('WP_CACHE', true);