各位观众老爷们,大家好!今天咱们来聊聊 WordPress 里一个看起来不起眼,但实际上非常重要的函数:get_rest_url()
。这货是干啥的呢?简单来说,它就是生成 WordPress REST API 的基础 URL 的。
你可能会想,URL 不就是个字符串吗?直接拼不就行了?理论上是没错,但 WordPress 这么成熟的系统,肯定不会让你这么粗暴。get_rest_url()
考虑了各种情况,比如子目录安装、自定义域名、HTTPS 等等,保证生成的 URL 是正确且可靠的。
咱们今天就来扒一扒 get_rest_url()
的源码,看看它是怎么工作的。准备好你的咖啡和键盘,Let’s go!
一、get_rest_url()
的基本用法
首先,咱们先看看 get_rest_url()
的基本用法。这货可以接受两个参数:
$path
(string, 可选): 要附加到基础 URL 的路径。默认为空字符串。$scheme
(string, 可选): 要使用的 URL 协议(’http’ 或 ‘https’)。如果为空,则使用当前请求的协议。
<?php
// 获取 REST API 的基础 URL
$base_url = get_rest_url();
echo $base_url; // 输出类似:http://example.com/wp-json/ (或者 https://example.com/wp-json/)
// 获取指定命名空间的 URL
$namespace_url = get_rest_url(null, 'myplugin/v1');
echo $namespace_url; // 输出类似:http://example.com/wp-json/myplugin/v1
// 强制使用 HTTPS 协议
$https_url = get_rest_url(null, 'myplugin/v1', 'https');
echo $https_url; // 输出类似:https://example.com/wp-json/myplugin/v1
?>
是不是很简单?接下来,咱们就要深入到源码里,看看这些 URL 到底是怎么生成的。
二、get_rest_url()
源码分析
get_rest_url()
的源码位于 wp-includes/rest-api.php
文件中。咱们来一段一段地剖析:
<?php
/**
* Retrieves the REST URL.
*
* @since 4.4.0
*
* @param string|null $path Optional. REST API path. Default null.
* @param string|null $scheme Optional. Scheme to use. Default null.
* @return string REST URL.
*/
function get_rest_url( $path = null, $scheme = null ) {
return get_url_from_relative( rest_get_url_prefix(), $path, $scheme );
}
嗯?就这么点?别急,这只是个入口函数。它调用了 get_url_from_relative()
和 rest_get_url_prefix()
这两个函数。咱们先来看看 rest_get_url_prefix()
:
<?php
/**
* Retrieves the REST API URL prefix.
*
* @since 4.4.0
*
* @return string REST prefix.
*/
function rest_get_url_prefix() {
/**
* Filters the REST API URL prefix.
*
* @since 4.4.0
*
* @param string $prefix URL prefix. Default 'wp-json'.
*/
return apply_filters( 'rest_url_prefix', 'wp-json' );
}
这个函数更简单,直接返回了 'wp-json'
字符串,并且提供了一个 rest_url_prefix
过滤器,允许你自定义 REST API 的 URL 前缀。如果你想把 'wp-json'
改成 'api'
,就可以使用这个过滤器。
接下来,咱们再来看看 get_url_from_relative()
:
<?php
/**
* Retrieves a full URL from a relative path.
*
* @since 4.7.0
*
* @param string $relative_url Relative URL.
* @param string|null $path Path to add to the URL.
* @param string|null $scheme Optional. Scheme to use. Default null.
* @return string Full URL.
*/
function get_url_from_relative( $relative_url, $path = null, $scheme = null ) {
$url = get_home_url( null, $relative_url, $scheme );
if ( ! empty( $path ) && is_string( $path ) ) {
$url .= '/' . ltrim( $path, '/' );
}
return $url;
}
这个函数才是真正的核心!它接收三个参数:
$relative_url
: 相对 URL,这里就是rest_get_url_prefix()
返回的'wp-json'
。$path
: 要附加到 URL 的路径。$scheme
: URL 协议。
这个函数首先使用 get_home_url()
获取 WordPress 的主页 URL,然后把相对 URL 附加到主页 URL 后面。最后,如果 $path
参数不为空,就把 $path
也附加到 URL 后面。
三、get_home_url()
的秘密
咱们上面提到了 get_home_url()
这个函数,它负责获取 WordPress 的主页 URL。这个函数也挺复杂的,咱们也来简单看一下:
<?php
/**
* Retrieves the URL for the home page.
*
* @since 2.2.0
*
* @param string|int|null $blog_id Optional. The blog ID. Default null.
* @param string $path Optional. Path relative to the home URL. Default null.
* @param string $scheme Optional. Scheme to use. Default null.
* @return string Home URL.
*/
function get_home_url( $blog_id = null, $path = '', $scheme = null ) {
return get_site_url( $blog_id, $path, $scheme );
}
嗯?又是一个简单的入口函数?没错,get_home_url()
实际上是调用了 get_site_url()
函数。
<?php
/**
* Retrieves the URL for a given site.
*
* @since 3.0.0
*
* @param int|null $blog_id Optional. Site ID. Default null (current site).
* @param string $path Optional. Path relative to the site URL. Default null.
* @param string|null $scheme Optional. Scheme to use. Default null.
* @return string Site URL.
*/
function get_site_url( $blog_id = null, $path = '', $scheme = null ) {
global $current_site;
if ( ! is_multisite() ) {
$url = home_url( $path, $scheme );
} else {
if ( empty( $blog_id ) ) {
$blog_id = get_current_blog_id();
}
$current_site = get_current_site();
$scheme = wp_allowed_protocols( $scheme );
if ( ! in_array( $scheme, array( 'http', 'https', 'relative' ), true ) ) {
$scheme = is_ssl() ? 'https' : 'http';
}
$site_url = get_network()->siteurl;
$path = ltrim( $path, '/' );
if ( $blog_id == get_main_site_id() || ( defined( 'DOMAIN_CURRENT_SITE' ) && DOMAIN_CURRENT_SITE == parse_url( $site_url, PHP_URL_HOST ) ) ) {
$url = set_url_scheme( $site_url, $scheme );
} else {
switch_to_blog( $blog_id );
$url = home_url( $path, $scheme );
restore_current_blog();
}
}
return $url;
}
get_site_url()
函数就比较复杂了,它考虑了单站点和多站点的情况。
- 单站点: 直接调用
home_url()
函数。 - 多站点: 首先获取当前站点的 ID,然后根据站点 ID 获取站点 URL。如果当前站点是主站点,就直接使用主站点的 URL。否则,就切换到当前站点,然后调用
home_url()
函数,最后再恢复到原来的站点。
咱们再来看看 home_url()
函数:
<?php
/**
* Retrieves the URL for the current site where the front end is accessible.
*
* @since 2.2.0
*
* @param string $path Optional. Path relative to the home URL. Default null.
* @param string|null $scheme Optional. Scheme to use. Default null.
* @return string Home URL.
*/
function home_url( $path = '', $scheme = null ) {
$orig_scheme = $scheme;
if ( defined( 'WP_HOME' ) ) {
$url = untrailingslashit( WP_HOME );
} else {
$url = get_option( 'home' );
}
if ( empty( $url ) ) {
$url = site_url();
}
$url = set_url_scheme( $url, $scheme );
if ( $path && is_string( $path ) ) {
$url .= '/' . ltrim( $path, '/' );
}
/**
* Filters the home URL.
*
* @since 2.9.0
*
* @param string $url The complete home URL including scheme and path.
* @param string $path Path relative to the home URL.
* @param string|null $orig_scheme Scheme to use.
*/
return apply_filters( 'home_url', $url, $path, $orig_scheme );
}
home_url()
函数首先检查是否定义了 WP_HOME
常量。如果定义了,就使用 WP_HOME
的值作为主页 URL。否则,就从 wp_options
表中获取 home
选项的值。如果 home
选项为空,就调用 site_url()
函数。最后,把 URL 协议设置为 $scheme
参数指定的值,并把 $path
参数附加到 URL 后面。
四、set_url_scheme()
的作用
咱们上面提到了 set_url_scheme()
函数,它负责设置 URL 的协议。这个函数也挺重要的,咱们也来简单看一下:
<?php
/**
* Sets the scheme for a URL.
*
* @since 2.7.0
*
* @param string $url The URL to set the scheme for.
* @param string|null $scheme The scheme to use. Must be 'http', 'https', 'relative', or null.
* @return string The URL with the updated scheme.
*/
function set_url_scheme( $url, $scheme = null ) {
$original_scheme = parse_url( $url, PHP_URL_SCHEME );
if ( ! $original_scheme ) {
$original_scheme = 'http';
}
if ( ! $scheme ) {
$scheme = is_ssl() ? 'https' : 'http';
}
if ( 'relative' === $scheme ) {
$scheme = '//';
}
$url = preg_replace( '|^' . preg_quote( $original_scheme, '|' ) . '://|', $scheme . '://', $url );
return $url;
}
set_url_scheme()
函数首先解析 URL,获取原来的协议。然后,如果 $scheme
参数为空,就根据当前是否使用 HTTPS 来设置协议。如果 $scheme
参数为 'relative'
,就把协议设置为 '//'
,表示使用相对协议。最后,使用正则表达式替换原来的协议。
五、总结
咱们来总结一下 get_rest_url()
函数的工作流程:
get_rest_url()
函数接收一个可选的路径和一个可选的协议作为参数。get_rest_url()
函数调用rest_get_url_prefix()
函数获取 REST API 的 URL 前缀,默认为'wp-json'
。get_rest_url()
函数调用get_url_from_relative()
函数,把 URL 前缀附加到 WordPress 的主页 URL 后面。get_url_from_relative()
函数调用get_home_url()
函数获取 WordPress 的主页 URL。get_home_url()
函数根据单站点和多站点的情况,调用home_url()
函数获取主页 URL。home_url()
函数首先检查是否定义了WP_HOME
常量,然后从wp_options
表中获取home
选项的值。home_url()
函数调用set_url_scheme()
函数设置 URL 的协议。get_url_from_relative()
函数把路径附加到 URL 后面。get_rest_url()
函数返回最终的 REST API URL。
为了更清晰地了解整个流程,咱们可以看下面这张表格:
函数名 | 功能 |
---|---|
get_rest_url() |
生成 REST API 的基础 URL,是入口函数。 |
rest_get_url_prefix() |
获取 REST API 的 URL 前缀,默认为 'wp-json' ,允许使用过滤器自定义。 |
get_url_from_relative() |
把相对 URL 附加到 WordPress 的主页 URL 后面,并处理路径参数。 |
get_home_url() |
获取 WordPress 的主页 URL,根据单站点和多站点的情况调用不同的函数。 |
get_site_url() |
获取指定站点的 URL,区分单站点和多站点,多站点时需要切换站点。 |
home_url() |
获取当前站点的主页 URL,考虑了 WP_HOME 常量和 home 选项,并允许使用过滤器自定义。 |
set_url_scheme() |
设置 URL 的协议,根据 $scheme 参数和当前是否使用 HTTPS 来设置协议,并处理 'relative' 协议。 |
六、实际应用场景
了解了 get_rest_url()
函数的工作原理,咱们来看看它在实际开发中有什么应用场景:
-
自定义 REST API 接口: 在开发自定义 REST API 接口时,需要使用
get_rest_url()
函数生成接口的 URL。<?php add_action( 'rest_api_init', function () { register_rest_route( 'myplugin/v1', '/items', array( 'methods' => 'GET', 'callback' => 'my_get_items', ) ); } ); function my_get_items( WP_REST_Request $request ) { // 处理请求 return array( 'message' => 'Hello from my plugin!' ); } // 获取接口的 URL $api_url = get_rest_url( null, 'myplugin/v1/items' ); echo $api_url; // 输出类似:http://example.com/wp-json/myplugin/v1/items ?>
-
前端 AJAX 请求: 在前端使用 AJAX 请求 REST API 接口时,需要使用
get_rest_url()
函数生成接口的 URL。// 获取接口的 URL var apiUrl = '<?php echo esc_url_raw( get_rest_url( null, 'myplugin/v1/items' ) ); ?>'; // 发送 AJAX 请求 fetch(apiUrl) .then(response => response.json()) .then(data => { console.log(data); // 输出:{message: "Hello from my plugin!"} });
-
插件设置页面: 在插件设置页面中,需要显示 REST API 接口的 URL,可以使用
get_rest_url()
函数生成 URL。
七、注意事项
在使用 get_rest_url()
函数时,需要注意以下几点:
- URL 编码: 如果
$path
参数包含特殊字符,需要进行 URL 编码,可以使用urlencode()
函数。 - HTTPS: 如果需要使用 HTTPS 协议,可以设置
$scheme
参数为'https'
。 - 缓存:
get_rest_url()
函数的结果可能会被缓存,如果需要获取最新的 URL,可以禁用缓存。
八、总结的总结
get_rest_url()
函数虽然看起来简单,但实际上考虑了很多情况,保证生成的 REST API URL 是正确且可靠的。通过深入了解 get_rest_url()
函数的源码,我们可以更好地理解 WordPress REST API 的工作原理,并在实际开发中更加灵活地使用它。
希望今天的讲解对大家有所帮助!下次再见!