阐述 WordPress `_wp_cache_reset_site_option_transients()` 函数的源码:在更新网络选项时如何清理缓存。

好嘞,各位观众老爷们,咱们今天来聊聊 WordPress 缓存清理界的一颗小星星,_wp_cache_reset_site_option_transients() 函数。别看名字长,其实它干的活儿挺实在的,就是负责在你更新网络选项的时候,把那些碍事的缓存给清理干净,免得你看到的是老旧的数据。

开场白:缓存的世界,爱恨交织

说起缓存,那真是让人又爱又恨。爱的是它能加速网站访问,恨的是它有时候会让你看到过时的信息。想象一下,你辛辛苦苦改了网站标题,结果隔了半天访问还是老标题,是不是很抓狂? 这就是缓存没及时更新的锅。

在 WordPress 中,缓存无处不在,从页面缓存到数据库查询缓存,各种缓存机制都在努力提升网站性能。而 transients(瞬态)就是一种比较常用的缓存机制,它可以用来存储一些临时性的数据,比如 API 请求的结果,或者一些计算量比较大的数据。

但是,transients 也存在一个问题,那就是它们也会过期。如果一个 transient 过期了,但是缓存系统没有及时清理,那么你就会看到过时的数据。更糟糕的是,如果你的网站使用了网络选项(Network Options),那么缓存清理的问题就会变得更加复杂。

网络选项:一个庞大的家族

网络选项是 WordPress 多站点模式下特有的,它允许你为整个网络设置一些全局性的选项。这些选项存储在 wp_sitemeta 表中,而不是像普通选项那样存储在 wp_options 表中。

由于网络选项是全局性的,所以当你更新一个网络选项的时候,你可能需要清理多个站点的缓存。这就是 _wp_cache_reset_site_option_transients() 函数发挥作用的地方。

源码剖析:一层层揭开它的神秘面纱

好了,废话不多说,让我们直接深入 _wp_cache_reset_site_option_transients() 函数的源码,看看它是如何工作的。

/**
 * Resets transients related to a specific network option.
 *
 * @since 3.5.0
 * @access private
 *
 * @param string $option Option name.
 */
function _wp_cache_reset_site_option_transients( $option ) {
    global $wpdb;

    $site_id = get_current_network_id();

    $like = esc_sql( $option );

    $query = "SELECT meta_key FROM {$wpdb->sitemeta} WHERE site_id = {$site_id} AND meta_key LIKE '_transient_%' AND meta_value LIKE '%{$like}%'";

    $transients = $wpdb->get_col( $query );

    if ( ! empty( $transients ) ) {
        foreach ( $transients as $transient ) {
            $key = str_replace( '_transient_', '', $transient );
            delete_site_transient( $key );
        }
    }

    $query = "SELECT meta_key FROM {$wpdb->sitemeta} WHERE site_id = {$site_id} AND meta_key LIKE '_site_transient_%' AND meta_value LIKE '%{$like}%'";

    $site_transients = $wpdb->get_col( $query );

    if ( ! empty( $site_transients ) ) {
        foreach ( $site_transients as $site_transient ) {
            $key = str_replace( '_site_transient_', '', $site_transient );
            delete_site_transient( $key );
        }
    }
}

让我们一行行地解读这段代码:

  1. function _wp_cache_reset_site_option_transients( $option ) {

    • 定义函数,接受一个参数 $option,表示要更新的网络选项的名称。
    • @access private 说明这是一个私有函数,通常不应该在主题或插件中直接调用。
  2. global $wpdb;

    • 声明使用全局变量 $wpdb,它是 WordPress 数据库操作的核心对象。
  3. $site_id = get_current_network_id();

    • 获取当前网络的 ID。在多站点模式下,每个站点都属于一个网络,这个函数可以获取当前站点的网络 ID。
  4. $like = esc_sql( $option );

    • $option 进行 SQL 转义,以防止 SQL 注入攻击。
  5. $query = "SELECT meta_key FROM {$wpdb->sitemeta} WHERE site_id = {$site_id} AND meta_key LIKE '_transient_%' AND meta_value LIKE '%{$like}%'";

    • 构建 SQL 查询语句,用于查询 wp_sitemeta 表中所有与 $option 相关的 transient
    • meta_key LIKE '_transient_%':筛选出所有以 _transient_ 开头的 meta_key,这些都是普通的 transient
    • meta_value LIKE '%{$like}%':筛选出 meta_value 中包含 $optiontransient。这个条件非常重要,因为它确保了我们只清理与指定选项相关的 transient
  6. $transients = $wpdb->get_col( $query );

    • 执行 SQL 查询,并将结果存储在 $transients 数组中。$wpdb->get_col() 函数用于获取查询结果中的某一列,这里我们获取的是 meta_key 列,也就是 transient 的名称。
  7. if ( ! empty( $transients ) ) { ... }

    • 判断 $transients 数组是否为空,如果不为空,则说明找到了与 $option 相关的 transient
  8. foreach ( $transients as $transient ) { ... }

    • 遍历 $transients 数组,对每一个 transient 执行清理操作。
  9. $key = str_replace( '_transient_', '', $transient );

    • transient 的名称中移除 _transient_ 前缀,得到真正的 transient key。
  10. delete_site_transient( $key );

    • 调用 delete_site_transient() 函数删除指定的 transient
  11. $query = "SELECT meta_key FROM {$wpdb->sitemeta} WHERE site_id = {$site_id} AND meta_key LIKE '_site_transient_%' AND meta_value LIKE '%{$like}%'";

    • 构建 SQL 查询语句,用于查询 wp_sitemeta 表中所有与 $option 相关的 site_transient
    • meta_key LIKE '_site_transient_%':筛选出所有以 _site_transient_ 开头的 meta_key,这些都是站点级别的 transient
    • meta_value LIKE '%{$like}%':筛选出 meta_value 中包含 $optionsite_transient
  12. $site_transients = $wpdb->get_col( $query );

    • 执行 SQL 查询,并将结果存储在 $site_transients 数组中。
  13. if ( ! empty( $site_transients ) ) { ... }

    • 判断 $site_transients 数组是否为空,如果不为空,则说明找到了与 $option 相关的 site_transient
  14. foreach ( $site_transients as $site_transient ) { ... }

    • 遍历 $site_transients 数组,对每一个 site_transient 执行清理操作。
  15. $key = str_replace( '_site_transient_', '', $site_transient );

    • site_transient 的名称中移除 _site_transient_ 前缀,得到真正的 site_transient key。
  16. delete_site_transient( $key );

    • 调用 delete_site_transient() 函数删除指定的 site_transient

工作流程:一图胜千言

为了更好地理解 _wp_cache_reset_site_option_transients() 函数的工作流程,我们可以用一张表格来概括:

步骤 描述 代码示例
1 获取当前网络 ID。 $site_id = get_current_network_id();
2 构建 SQL 查询语句,查找与指定网络选项相关的普通 transient $query = "SELECT meta_key FROM {$wpdb->sitemeta} WHERE site_id = {$site_id} AND meta_key LIKE '_transient_%' AND meta_value LIKE '%{$like}%'";
3 执行 SQL 查询,获取所有相关的普通 transient 名称。 $transients = $wpdb->get_col( $query );
4 遍历所有相关的普通 transient 名称,移除 _transient_ 前缀,并使用 delete_site_transient() 函数删除它们。 $key = str_replace( '_transient_', '', $transient ); delete_site_transient( $key );
5 构建 SQL 查询语句,查找与指定网络选项相关的站点级别的 transient $query = "SELECT meta_key FROM {$wpdb->sitemeta} WHERE site_id = {$site_id} AND meta_key LIKE '_site_transient_%' AND meta_value LIKE '%{$like}%'";
6 执行 SQL 查询,获取所有相关的站点级别的 transient 名称。 $site_transients = $wpdb->get_col( $query );
7 遍历所有相关的站点级别的 transient 名称,移除 _site_transient_ 前缀,并使用 delete_site_transient() 函数删除它们。 $key = str_replace( '_site_transient_', '', $site_transient ); delete_site_transient( $key );

触发时机:幕后英雄的默默奉献

那么,_wp_cache_reset_site_option_transients() 函数在什么时候会被调用呢?

它主要在 update_site_option() 函数中被调用。当你使用 update_site_option() 函数更新一个网络选项的时候,WordPress 会自动调用 _wp_cache_reset_site_option_transients() 函数,以确保相关的缓存被清理干净。

/**
 * Updates the value of a network option.
 *
 * @since 3.0.0
 *
 * @param string $option  Name of the network option.
 * @param mixed  $value   Value of the network option.
 * @return bool True if the value was updated, false otherwise.
 */
function update_site_option( $option, $value ) {
    // ... (省略部分代码) ...

    /**
     * Fires immediately after a site option is updated.
     *
     * @since 3.0.0
     *
     * @param string $option Name of the network option.
     */
    do_action( 'update_site_option', $option );

    /**
     * Fires after the value of a specific network option has been successfully updated.
     *
     * The dynamic portion of the hook name, `$option`, refers to the name of the
     * option being updated.
     *
     * @since 3.0.0
     *
     * @param mixed $old_value The old option value.
     * @param mixed $value     The new option value.
     */
    do_action( "update_site_option_{$option}", $old_value, $value );

    wp_cache_delete( 'alloptions', 'site-options' );

    _wp_cache_reset_site_option_transients( $option ); // 这里调用了 _wp_cache_reset_site_option_transients() 函数

    return true;
}

可以看到,在 update_site_option() 函数的最后,_wp_cache_reset_site_option_transients( $option ) 被调用,传入了被更新的网络选项的名称。

注意事项:细节决定成败

在使用 _wp_cache_reset_site_option_transients() 函数的时候,有一些需要注意的地方:

  • 不要直接调用它: _wp_cache_reset_site_option_transients() 是一个私有函数,通常不应该在主题或插件中直接调用。你应该使用 update_site_option() 函数来更新网络选项,WordPress 会自动处理缓存清理的问题。
  • 理解 transient 的工作原理: transient 是一种缓存机制,它有过期时间。如果一个 transient 过期了,即使你调用了 _wp_cache_reset_site_option_transients() 函数,它也可能不会被清理,因为 WordPress 已经认为它过期了。
  • 考虑缓存插件的影响: 如果你使用了缓存插件,那么缓存清理的行为可能会受到插件的影响。一些缓存插件可能会有自己的缓存清理机制,可能会覆盖 WordPress 的默认行为。

总结:小函数,大作用

_wp_cache_reset_site_option_transients() 函数虽然看起来不起眼,但它在 WordPress 多站点模式下起着非常重要的作用。它确保了当你更新网络选项的时候,相关的缓存能够被及时清理,从而避免了数据不一致的问题。

下次当你修改了 WordPress 网络选项,发现前台没有及时更新,不妨想想是不是缓存在作怪,然后回忆一下今天我们讲的 _wp_cache_reset_site_option_transients() 函数,也许它就能帮你找到问题的根源。

结束语:缓存之路,永无止境

好了,今天的讲座就到这里。希望通过今天的讲解,大家对 _wp_cache_reset_site_option_transients() 函数有了更深入的了解。 缓存的世界博大精深,还有很多值得我们去探索的地方。希望大家在缓存的道路上越走越远,成为真正的缓存大师! 感谢各位观众老爷的观看,咱们下期再见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注