分析 WordPress `get_site_option()` 函数源码:它在多站点模式下与 `get_option()` 有何不同。

各位程序猿、攻城狮、代码艺术家们,大家好!我是老码农,今天咱们来扒一扒 WordPress 里一对儿看似相像,实则有点小脾气的函数:get_site_option()get_option()

开场白:话说江湖事,选项也分家

在 WordPress 的世界里,选项就像江湖里的秘籍,记录着各种门派的独门绝技——插件设置、主题风格等等。get_option() 就像是每个门派自己保管的秘籍副本,而 get_site_option() 则像是武林盟主手里那份总纲,记录着整个武林的规则。

在单站点模式下,get_option() 就可以打遍天下无敌手,但在多站点模式下,get_site_option() 就显得尤为重要了。 接下来,我们就深入源代码,看看它们到底有啥不同。

第一幕:get_option() 的独角戏

首先,让我们回顾一下 get_option()。 这个函数的作用是根据给定的选项名($option),从 WordPress 的 wp_options 表中获取对应的选项值。 如果找到了,就返回选项值;如果没找到,就返回一个默认值(通常是 false)。

咱们看看 get_option() 的简化版代码(为了便于理解,我省略了一些细节):

function get_option( $option, $default = false ) {
    global $wpdb;
    static $notoptions;

    if ( isset( $notoptions[ $option ] ) ) {
        return $default;
    }

    $alloptions = wp_load_alloptions(); // 加载所有自动加载的选项

    if ( isset( $alloptions[ $option ] ) ) {
        return apply_filters( 'pre_option_' . $option, $alloptions[ $option ] );
    }

    $row = $wpdb->get_row( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", $option ) );

    if ( is_object( $row ) ) {
        $value = $row->option_value;
        $value = maybe_unserialize( $value );
        $value = apply_filters( 'pre_option_' . $option, $value );
        return $value;
    } else {
        $notoptions[ $option ] = true;
        return apply_filters( 'pre_option_' . $option, $default );
    }
}

这段代码的核心逻辑是:

  1. 缓存检查: 先看静态变量 $notoptions 里有没有记录过这个选项,如果有,说明之前没找到过,直接返回默认值。
  2. 自动加载选项检查: 检查 $alloptions 数组 (由 wp_load_alloptions() 函数加载) 中是否已经存在该选项。如果存在,直接返回。 wp_load_alloptions() 从数据库读取所有 autoloadyes 的选项,存入缓存。
  3. 数据库查询: 如果缓存里没有,就直接去 wp_options 表里查,查到了就反序列化,然后返回;没查到就在 $notoptions 里记一笔,下次就不用查了,直接返回默认值。

第二幕:get_site_option() 的登场

现在,主角 get_site_option() 闪亮登场了。 在多站点模式下,每个站点都有自己的 wp_options 表,而 get_site_option() 则是用来获取整个网络(network)级别的选项的。

get_site_option() 的代码看起来有点复杂,但核心思路其实很简单:

function get_site_option( $option, $default = false ) {
    global $wpdb, $wp_current_db_version;
    static $sitedata = array();

    if ( isset( $sitedata[ $option ] ) ) {
        return $sitedata[ $option ];
    }

    $network_id = get_current_site()->id;

    $key = $option . '_' . $network_id;

    $value = wp_cache_get( $key, 'site-options' );

    if ( false !== $value ) {
        $sitedata[ $option ] = $value;
        return $value;
    }

    $row = $wpdb->get_row( $wpdb->prepare( "SELECT option_value FROM $wpdb->sitemeta WHERE site_id = %d AND meta_key = %s", $network_id, $option ) );

    if ( is_object( $row ) ) {
        $value = $row->option_value;
        $value = maybe_unserialize( $value );
    } else {
        $value = get_network_option(null, $option, $default);  //Fallback到get_network_option

        if($value === $default){
            $value = $default;
        }
    }

    wp_cache_set( $key, $value, 'site-options' );
    $sitedata[ $option ] = $value;

    return $value;
}

我们来分解一下:

  1. 静态缓存: 同样,先检查静态变量 $sitedata 里有没有缓存,有就直接返回。
  2. 缓存键构建: 构建缓存键,将选项名和当前站点的网络 ID 组合起来,确保缓存的唯一性。
  3. WP Cache 检查: 使用 WordPress 的对象缓存(WP Cache)来检查是否有缓存,有就直接返回。 WP Cache 是一个强大的缓存系统,可以显著提高性能。
  4. 数据库查询: 如果缓存里没有,就去 wp_sitemeta 表里查,这个表专门存储网络级别的选项。 注意,这里用到了 site_id,也就是网络 ID。
  5. 反序列化: 查到了就反序列化。
  6. Fallback到get_network_option: 如果在 wp_sitemeta 表中没有找到,则 fallback 到 get_network_optionget_network_option 允许指定网络ID,如果没有指定,则使用当前网络ID。 这允许从特定的网络或主网络获取选项。
  7. 缓存设置: 最后,把查到的结果放进 WP Cache 和静态变量 $sitedata 里,方便下次使用。

第三幕:多站点模式下的恩怨情仇

现在,我们来总结一下 get_option()get_site_option() 在多站点模式下的区别:

特性 get_option() get_site_option()
存储位置 每个站点的 wp_options wp_sitemeta 表 (存储网络级别的选项)
作用域 单个站点 整个网络(所有站点共享)
使用场景 获取特定站点的设置,比如主题设置、插件设置等 获取整个网络的设置,比如网络管理员邮箱、注册设置等
数据表 wp_options wp_sitemeta

举个例子:

  • 假设你想获取每个站点的主题颜色设置,你应该用 get_option( 'theme_color' )
  • 假设你想获取整个网络的注册设置,比如是否允许用户注册,你应该用 get_site_option( 'registration' )

第四幕:代码实战

为了更好地理解,我们来写几个简单的例子:

例子 1:获取当前站点的主题颜色

$theme_color = get_option( 'theme_color', '#ffffff' ); // 默认白色
echo '当前站点的主题颜色是:' . $theme_color;

例子 2:获取网络管理员邮箱

$admin_email = get_site_option( 'admin_email' );
echo '网络管理员邮箱是:' . $admin_email;

例子 3:设置和获取站点选项

// 设置站点选项
update_option( 'my_custom_option', 'Hello World!' );

// 获取站点选项
$my_option = get_option( 'my_custom_option' );
echo '我的站点选项是:' . $my_option;

例子 4:设置和获取网络选项

// 设置网络选项
update_site_option( 'my_custom_site_option', 'Hello Network!' );

// 获取网络选项
$my_site_option = get_site_option( 'my_custom_site_option' );
echo '我的网络选项是:' . $my_site_option;

第五幕:update_option()update_site_option() 的配合

既然说了 get_option()get_site_option(),就不得不提一下它们的好基友:update_option()update_site_option()

  • update_option( $option, $value ):用于更新单个站点的选项。
  • update_site_option( $option, $value ):用于更新整个网络的选项。

它们的代码逻辑也和 get_option()get_site_option() 类似,我就不一一展开了,大家可以自己去研究一下。

第六幕:总结陈词

好了,今天的讲座就到这里。 咱们深入剖析了 get_site_option()get_option() 的源码,了解了它们在多站点模式下的区别和使用场景。

简单来说:

  • get_option() 负责管理单个站点的选项,存储在 wp_options 表里。
  • get_site_option() 负责管理整个网络的选项,存储在 wp_sitemeta 表里。

记住,在多站点模式下,一定要根据选项的作用域选择正确的函数,否则可能会出现意想不到的问题。

希望今天的讲解对大家有所帮助。 记住,代码的世界是充满乐趣的,只要你肯钻研,就能发现更多的奥秘。 下次再见!

发表回复

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