各位代码界的吃瓜群众,大家好!我是今天的主讲人,咱们今天唠唠 WordPress 多站点模式下 get_site_url()
这个函数背后的故事,看看它是怎么变戏法儿,给你变出一个个站点的 URL 的。
开场白:get_site_url()
的自我介绍
首先,咱们得认识一下今天的主角 get_site_url()
。简单来说,这个函数的作用就是获取站点的 URL。听起来很简单是不是?但如果你在多站点环境下,情况就稍微复杂一点了。因为它需要知道你想获取哪个站点的 URL。就像你去一家连锁店,总得告诉店员你想去哪家分店吧?
单站点与多站点的 URL 区别
在单站点环境下,get_site_url()
通常直接返回 WP_HOME
选项的值。这个选项的值在 WordPress 安装的时候就已经确定了,通常是你的网站域名。
// 单站点环境下的简化版 get_site_url() (仅为演示)
function my_get_site_url() {
return get_option( 'home' ); // 实际上 WordPress 使用 WP_HOME 常量,但这里为了简化演示
}
但是,多站点环境下,每个站点都有自己的 URL,这些 URL 可能基于子域名或子目录。所以 get_site_url()
需要更智能地知道你想获取哪个站点的 URL。
多站点模式的两种类型:子域名和子目录
在 WordPress 多站点中,站点 URL 的生成方式取决于你选择了哪种模式:
- 子域名 (Subdomain): 比如
site1.example.com
,site2.example.com
。每个站点都有自己的子域名。 - 子目录 (Subdirectory): 比如
example.com/site1
,example.com/site2
。每个站点都在主站点的子目录下。
这两种模式直接影响 get_site_url()
的实现方式。
源码分析:get_site_url()
的庐山真面目
咱们现在直接扒开源码,看看 get_site_url()
到底是怎么工作的。因为 WordPress 源码比较庞大,这里提取了关键部分,并做了一些简化,方便大家理解。
// WordPress 源码 (简化版)
function get_site_url( $blog_id = null, $path = '', $scheme = null ) {
global $current_site, $current_blog;
// 1. 确定 Blog ID
if ( null === $blog_id ) {
if ( isset( $current_blog ) && is_object( $current_blog ) ) {
$blog_id = $current_blog->blog_id;
} else {
$blog_id = get_current_blog_id();
}
}
// 2. 获取站点的 Domain 和 Path
$details = get_site( $blog_id );
if ( ! $details ) {
return false; // 如果站点不存在,返回 false
}
$domain = $details->domain;
$path = $details->path;
// 3. 构建 URL
$url = $scheme . '://' . $domain . $path;
// 4. 拼接 path 参数
if ( ! empty( $path ) ) {
$url = trailingslashit( $url );
}
if ( ! empty( $path ) && is_string( $path ) && ( substr( $path, 0, 1 ) == '/' ) ) {
$path = substr( $path, 1 );
}
if ( $path ) {
$url .= $path;
}
return $url;
}
function get_site( $id = 0 ) {
global $wpdb;
if ( empty( $id ) ) {
$id = get_current_network_id();
}
$key = $id . ':site';
$cache = wp_cache_get( $key, 'site-details' );
if ( false === $cache ) {
$id = (int) $id;
if ( ! $id ) {
return false;
}
$cache = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->site} WHERE id = %d", $id ) );
if ( empty( $cache ) ) {
return false;
}
wp_cache_set( $key, $cache, 'site-details' );
}
return $cache;
}
function get_current_blog_id() {
global $current_blog;
if ( ! empty( $current_blog ) && is_object( $current_blog ) ) {
return (int) $current_blog->blog_id;
}
if ( defined( 'SITE_ID_CURRENT_SITE' ) ) {
return (int) SITE_ID_CURRENT_SITE;
}
return 1;
}
咱们一步一步地来解读这段代码:
-
确定 Blog ID (
$blog_id
):- 首先,
get_site_url()
接受一个可选的$blog_id
参数,用于指定你要获取哪个站点的 URL。如果没传这个参数,它会尝试从全局变量$current_blog
中获取,或者使用get_current_blog_id()
函数。 get_current_blog_id()
也很简单,也是优先从全局变量$current_blog
获取,如果获取不到就返回SITE_ID_CURRENT_SITE
常量。
- 首先,
-
获取站点的 Domain 和 Path:
- 通过
get_site( $blog_id )
函数,从数据库中获取指定$blog_id
的站点的详细信息,包括domain
(域名) 和path
(路径)。 get_site()
函数内部会先尝试从缓存中获取站点信息,如果缓存没有,就从数据库的wp_site
表中查询。
- 通过
-
构建 URL:
- 将
$scheme
(协议,比如http
或https
)、$domain
(域名) 和$path
(路径) 拼接起来,构成基本的 URL。 协议的获取这里省略了,实际源码会根据情况选择https
还是http
。
- 将
-
处理 Path 参数:
- 如果
$path
参数不为空,将它添加到 URL 的末尾。 - 去除
$path
参数开头的斜杠,防止 URL 中出现多余的斜杠。
- 如果
重点:wp_site
表长啥样?
wp_site
表存储了多站点网络中每个站点的基本信息,包括:
字段 | 类型 | 描述 |
---|---|---|
id |
bigint(20) unsigned | 站点 ID,唯一标识符 |
domain |
varchar(200) | 站点的域名,比如 site1.example.com 或 example.com |
path |
varchar(100) | 站点的路径,比如 / 或 /site1 。注意:必须以 / 开头,即使是根目录 / ,也不能是空字符串。 |
案例分析:子域名模式下的 URL 生成
假设我们有一个多站点网络,使用子域名模式,并且有以下站点:
站点 ID | 域名 | 路径 |
---|---|---|
1 | example.com |
/ |
2 | site1.example.com |
/ |
3 | site2.example.com |
/ |
如果我们调用 get_site_url(2)
,会发生什么?
get_site_url(2)
会先确定$blog_id
为 2。get_site(2)
会从wp_site
表中查询 ID 为 2 的站点信息,得到域名为site1.example.com
,路径为/
。get_site_url(2)
将https
(假设我们使用 HTTPS) +://
+site1.example.com
+/
拼接起来,得到https://site1.example.com/
。
案例分析:子目录模式下的 URL 生成
假设我们有一个多站点网络,使用子目录模式,并且有以下站点:
站点 ID | 域名 | 路径 |
---|---|---|
1 | example.com |
/ |
2 | example.com |
/site1/ |
3 | example.com |
/site2/ |
如果我们调用 get_site_url(2)
,会发生什么?
get_site_url(2)
会先确定$blog_id
为 2。get_site(2)
会从wp_site
表中查询 ID 为 2 的站点信息,得到域名为example.com
,路径为/site1/
。get_site_url(2)
将https
(假设我们使用 HTTPS) +://
+example.com
+/site1/
拼接起来,得到https://example.com/site1/
。
get_site_url()
与 home_url()
的区别
很多同学可能会疑惑,get_site_url()
和 home_url()
都是获取 URL 的,它们有什么区别呢?
get_site_url()
: 获取的是站点的 URL,也就是wp_site
表中存储的域名和路径的组合。home_url()
: 获取的是首页的 URL,它会考虑WP_HOME
选项的值,并且可以添加额外的路径。
简单来说,get_site_url()
更底层,直接从数据库获取站点信息;home_url()
更灵活,可以根据需求添加路径。
network_site_url()
除了 get_site_url()
,还有一个函数 network_site_url()
。这个函数与 get_site_url()
的区别在于,network_site_url()
获取的是 网络 的 URL,而不是单个站点的 URL。它通常用于获取主站点的 URL。
总结:get_site_url()
的核心思想
get_site_url()
的核心思想是:
- 确定要获取哪个站点的 URL (
$blog_id
)。 - 从数据库中获取该站点的域名和路径。
- 将域名和路径拼接起来,构成完整的 URL。
一些注意事项
get_site_url()
返回的 URL 不包含尾部的斜杠。如果你需要尾部斜杠,可以使用trailingslashit()
函数。get_site_url()
可以接受第三个参数$scheme
,用于指定 URL 的协议 (http 或 https)。- 在多站点环境中,正确配置
wp-config.php
文件非常重要,包括WP_ALLOW_MULTISITE
、MULTISITE
、SUBDOMAIN_INSTALL
、DOMAIN_CURRENT_SITE
、PATH_CURRENT_SITE
、SITE_ID_CURRENT_SITE
和BLOG_ID_CURRENT_SITE
等常量。
实战演练:在主题中使用 get_site_url()
假设我们想在主题中显示当前站点的 URL,可以这样写:
<?php
$site_url = get_site_url();
echo '<p>当前站点的 URL 是:' . esc_url( $site_url ) . '</p>';
?>
进阶:使用过滤器修改 get_site_url()
的行为
WordPress 提供了 site_url
过滤器,允许你修改 get_site_url()
的返回值。这在某些特殊情况下非常有用,比如你想根据用户的角色动态地修改站点的 URL。
add_filter( 'site_url', 'my_custom_site_url', 10, 3 );
function my_custom_site_url( $url, $path, $blog_id ) {
// 在这里添加你的逻辑
if ( is_user_logged_in() && current_user_can( 'administrator' ) ) {
// 管理员访问时,添加一个特殊的参数
$url = add_query_arg( 'admin_mode', 'true', $url );
}
return $url;
}
结束语:get_site_url()
的重要性
get_site_url()
是 WordPress 多站点中一个非常重要的函数,它负责生成站点的 URL,是多站点正常运行的基础。理解它的工作原理,可以帮助你更好地理解 WordPress 多站点的架构,并在开发主题和插件时更加得心应手。
好了,今天的讲座就到这里。希望通过今天的讲解,大家对 get_site_url()
有了更深入的了解。下次再遇到它,就不会觉得陌生了。记住,代码的世界充满了乐趣,只要你愿意探索,就能发现更多的惊喜!
感谢大家的收听,祝大家编码愉快!