分析 WordPress `wp_get_network()` 函数的源码:如何获取当前网络或指定网络的 `WP_Network` 对象。

观众朋友们,晚上好!我是你们的老朋友,今晚咱们来聊聊 WordPress 里一个相当关键,但又经常被忽视的函数:wp_get_network()。 别看它名字平平无奇,它可是 WordPress Multisite (多站点) 功能的核心支柱之一。 想象一下,Multisite 就像一个大型购物中心,而每个站点就像一个独立的店铺。wp_get_network() 就好比是购物中心的总服务台,负责告诉你整个购物中心的信息,或者某个特定区域(网络)的信息。

那么,这个“服务台”到底是怎么工作的呢?让我们一起深入源码,揭开它的神秘面纱。

1. wp_get_network():它的职责和参数

首先,我们要明确 wp_get_network() 的主要职责:获取一个 WP_Network 对象。 这个对象包含了关于整个网络或者特定网络的信息,比如网络 ID、域名、路径等等。

wp_get_network() 函数接受一个可选的参数:

  • $network_id: (int|WP_Network|null) 网络 ID。 如果传入一个 WP_Network 对象,它会直接返回这个对象。如果传入 null (默认值),它会尝试获取当前的网络。

函数签名看起来像这样:

function wp_get_network( $network_id = null ) {
    // 函数体
}

2. 源码剖析:一步步追踪网络信息

接下来,我们来一步步地分析 wp_get_network() 的源码,看看它是如何获取网络信息的。 为了更清晰地展示,我们把代码拆分成几个关键部分来讲解:

2.1 参数处理和缓存检查

function wp_get_network( $network_id = null ) {
    global $wpdb;

    // 如果传入的是 WP_Network 对象,直接返回
    if ( $network_id instanceof WP_Network ) {
        return $network_id;
    }

    // 如果没有传入 network_id,尝试获取当前网络 ID
    if ( empty( $network_id ) ) {
        $network_id = get_current_network_id();
    }

    $network_id = (int) $network_id;

    if ( empty( $network_id ) ) {
        return null;
    }

    // 尝试从缓存中获取
    $network = wp_cache_get( $network_id, 'networks' );
    if ( false !== $network ) {
        return $network;
    }

这段代码首先检查传入的参数是否是一个 WP_Network 对象。如果是,直接返回,避免重复操作。 如果 $network_id 为空,则调用 get_current_network_id() 来获取当前网络的 ID。 然后,将 $network_id 强制转换为整数类型。 确保 $network_id 不为空。如果为空,直接返回 null

最后,尝试从 WordPress 的对象缓存中获取网络信息。 wp_cache_get() 函数会根据 $network_id 和缓存组 'networks' 来查找缓存中是否存在对应的网络信息。 如果找到,直接返回缓存中的 WP_Network 对象,这大大提高了性能。

2.2 从数据库中加载网络信息

如果缓存中没有找到,就需要从数据库中加载网络信息了。

    $network = false;

    // 从数据库中加载
    $network_data = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->site} WHERE id = %d", $network_id ), OBJECT );

    if ( empty( $network_data ) ) {
        return null;
    }

这里使用了 $wpdb 对象,它是 WordPress 内置的数据库操作类。 $wpdb->get_row() 函数执行一个 SQL 查询,从 {$wpdb->site} 表(通常是 wp_site 表)中获取指定 ID 的网络信息。

$wpdb->prepare() 函数用于预处理 SQL 查询,防止 SQL 注入攻击。 OBJECT 参数指定返回结果的格式为对象。

如果查询结果为空,说明数据库中不存在该 ID 的网络,函数返回 null

2.3 创建 WP_Network 对象并缓存

如果成功从数据库中获取了网络信息,接下来就要创建一个 WP_Network 对象,并将其缓存起来,以便下次使用。

    $network = new WP_Network( $network_data );

    wp_cache_set( $network_id, $network, 'networks' );

    return $network;
}

这里,我们使用从数据库中获取的 $network_data 创建了一个新的 WP_Network 对象。 然后,使用 wp_cache_set() 函数将这个对象缓存起来,缓存键是 $network_id,缓存组是 'networks'

最后,返回创建好的 WP_Network 对象。

3. WP_Network 对象:网络的容器

WP_Network 类是 WordPress 中用于表示网络信息的类。 它封装了网络的各种属性,比如 ID、域名、路径等等。

WP_Network 类的定义如下(简化版):

class WP_Network {
    public $id;
    public $domain;
    public $path;
    public $site_id;
    public $registered;
    public $last_updated;

    public function __construct( $network ) {
        foreach ( get_object_vars( $network ) as $key => $value ) {
            $this->$key = $value;
        }
    }

    // 其他方法
}

WP_Network 类的构造函数接收一个网络数据对象(通常是从数据库中获取的),并将对象的属性赋值给 WP_Network 对象的属性。

通过 WP_Network 对象,我们可以方便地访问网络的各种信息,比如:

$network = wp_get_network( 1 ); // 获取 ID 为 1 的网络

if ( $network ) {
    echo '网络 ID: ' . $network->id . '<br>';
    echo '域名: ' . $network->domain . '<br>';
    echo '路径: ' . $network->path . '<br>';
}

4. get_current_network_id():如何获取当前网络 ID?

刚才我们提到了 get_current_network_id() 函数,它用于获取当前网络的 ID。 这个函数的实现比较复杂,因为它需要考虑各种情况,比如是否定义了 DOMAIN_CURRENT_SITE 常量、是否在后台等等。

我们来看一下 get_current_network_id() 函数的源码:

function get_current_network_id() {
    global $current_site, $wpdb;

    // 如果已经设置了 $current_site,直接返回它的 ID
    if ( isset( $current_site ) && isset( $current_site->id ) ) {
        return (int) $current_site->id;
    }

    // 如果定义了 DOMAIN_CURRENT_SITE 常量,尝试从数据库中获取
    if ( defined( 'DOMAIN_CURRENT_SITE' ) && defined( 'PATH_CURRENT_SITE' ) ) {
        $domain = DOMAIN_CURRENT_SITE;
        $path   = PATH_CURRENT_SITE;

        $current_site = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->site} WHERE domain = %s AND path = %s", $domain, $path ) );

        if ( $current_site ) {
            return (int) $current_site->id;
        }
    }

    // 如果在后台,并且是新安装的站点,尝试获取
    if ( is_admin() && defined( 'WP_INSTALLING' ) ) {
        $current_site = $wpdb->get_row( "SELECT * FROM {$wpdb->site} WHERE id = 1" );
        if ( $current_site ) {
            return (int) $current_site->id;
        }
    }

    // 默认情况下,返回 1
    return 1;
}

这段代码的逻辑如下:

  1. 检查 $current_site 全局变量: 如果 $current_site 已经设置,直接返回它的 id 属性。 $current_site 是一个全局变量,用于存储当前站点的信息。

  2. 检查 DOMAIN_CURRENT_SITEPATH_CURRENT_SITE 常量: 如果定义了 DOMAIN_CURRENT_SITEPATH_CURRENT_SITE 常量,说明这是在 wp-config.php 文件中手动配置了网络信息。 然后,根据这两个常量的值,从数据库中查询对应的网络信息,并返回其 ID。

  3. 检查是否在后台安装: 如果在后台,并且定义了 WP_INSTALLING 常量,说明正在进行 WordPress 的安装。 在这种情况下,默认返回 ID 为 1 的网络。

  4. 默认值: 如果以上条件都不满足,默认返回 1。 这通常发生在单站点环境中。

5. 使用场景和示例

wp_get_network() 函数在 WordPress Multisite 中扮演着重要的角色。 以下是一些常见的使用场景:

  • 获取当前网络的信息:

    $network = wp_get_network(); // 不传入参数,获取当前网络
    if ( $network ) {
        echo '当前网络域名: ' . $network->domain;
    }
  • 获取指定网络的信息:

    $network = wp_get_network( 2 ); // 获取 ID 为 2 的网络
    if ( $network ) {
        echo '指定网络路径: ' . $network->path;
    }
  • 在插件或主题中使用:

    function my_plugin_get_network_domain( $network_id ) {
        $network = wp_get_network( $network_id );
        if ( $network ) {
            return $network->domain;
        }
        return '';
    }
    
    echo '网络域名: ' . my_plugin_get_network_domain( 3 );

6. 总结:wp_get_network() 的价值

wp_get_network() 函数是 WordPress Multisite 功能的核心组成部分。 它提供了一种方便、高效的方式来获取网络信息,并将其封装在 WP_Network 对象中。 通过分析它的源码,我们可以更深入地了解 WordPress Multisite 的工作原理,并更好地利用它来构建复杂的网络应用。

表格总结

为了更好地总结 wp_get_network() 函数,我们用一个表格来概括它的主要功能和流程:

步骤 描述 涉及的函数/类
1 参数处理:检查参数类型,获取网络 ID wp_get_network(), get_current_network_id()
2 缓存检查:尝试从缓存中获取 WP_Network 对象 wp_cache_get()
3 数据库查询:如果缓存中没有找到,从数据库中加载网络信息 $wpdb->get_row(), $wpdb->prepare()
4 对象创建:创建 WP_Network 对象 WP_Network
5 缓存更新:将 WP_Network 对象缓存起来 wp_cache_set()
6 返回结果:返回 WP_Network 对象或 null wp_get_network()

一些需要注意的点:

  • 在 Multisite 环境中,wp_get_network() 函数非常重要,但在单站点环境中,它的作用相对较小。
  • WP_Network 对象是只读的,不能直接修改它的属性来更新网络信息。 要更新网络信息,需要使用其他函数,比如 wp_update_network()
  • 合理利用 WordPress 的对象缓存可以提高性能,减少数据库查询。

好了,今天的讲座就到这里。 希望通过今天的讲解,大家对 wp_get_network() 函数有了更深入的理解。 记住,理解源码是成为 WordPress 大牛的必经之路! 祝大家编程愉快!下课!

发表回复

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