探究 WordPress `is_rest_api_request()` 函数的源码:如何判断当前请求是否为 REST API。

各位观众老爷,晚上好!今天咱们来聊聊WordPress里一个相当低调,但关键时刻又能顶大用的函数:is_rest_api_request()。这玩意儿就像个秘密警察,专门负责侦察你的请求是不是冲着REST API来的。别小看它,弄清楚它怎么工作的,能帮你更好地理解WordPress的REST API机制,甚至能让你在开发插件或者主题的时候少踩不少坑。

咱们争取用最接地气的方式,把这个函数扒个精光,让大家以后再遇到它,就像老朋友一样亲切。

开场白:REST API的重要性

在深入代码之前,先简单聊聊REST API的重要性。 想象一下,如果没有REST API,你的手机APP、其他网站、甚至你家里的智能冰箱,都无法直接跟你的WordPress网站对话。它们只能通过复杂的、定制化的方式来获取或者修改数据,效率低下,维护困难。

REST API就像一个翻译官,它把WordPress的数据和功能翻译成通用的语言(通常是JSON),让各种不同的客户端都能轻松理解和使用。 这也正是WordPress拥抱Headless CMS概念的关键所在。

is_rest_api_request():你的专属REST API侦探

那么, is_rest_api_request() 这个函数到底是怎么判断一个请求是不是REST API请求的呢? 让我们一起深入WordPress的源码,一探究竟。

第一步:找到is_rest_api_request()的藏身之处

这个函数定义在 wp-includes/functions.php 文件中。直接找到这个文件,或者在你的代码编辑器里搜索 is_rest_api_request,就能找到它的庐山真面目。

第二步:解剖源码,看看它到底做了什么

以下是 is_rest_api_request() 函数的源码:

function is_rest_api_request() {
    global $wp;

    if ( empty( $wp ) || ! is_object( $wp ) ) {
        return false;
    }

    if ( empty( $wp->request ) ) {
        return false;
    }

    $rest_prefix = trailingslashit( rest_get_url_prefix() );

    return ( strpos( $wp->request, $rest_prefix ) === 0 );
}

这段代码看起来是不是很简单? 别怕,咱们一句一句地分析。

  1. 全局变量 $wp:WordPress的核心

    global $wp;

    首先,它声明了一个全局变量 $wp。这个 $wp 对象是WordPress的核心,包含了当前请求的各种信息,比如请求的URL、查询参数等等。 我们可以把它想象成一个装着当前请求所有信息的百宝箱。

    如果 $wp 为空或者不是一个对象,那说明WordPress还没完全加载,或者发生了什么奇怪的事情,这种情况下肯定不是REST API请求,直接返回 false

    if ( empty( $wp ) || ! is_object( $wp ) ) {
        return false;
    }
  2. 检查 $wp->request:请求的URI

    if ( empty( $wp->request ) ) {
        return false;
    }

    接下来,它检查 $wp->request 是否为空。$wp->request 包含了请求的URI(统一资源标识符),也就是浏览器地址栏里除了域名之外的部分。 比如,如果你的网站地址是 https://example.com,而你访问的是 https://example.com/wp-json/wp/v2/posts,那么 $wp->request 的值就是 /wp-json/wp/v2/posts。 如果 $wp->request 为空,那肯定也不是REST API请求,直接返回 false

  3. 获取 REST API 的 URL 前缀:rest_get_url_prefix()

    $rest_prefix = trailingslashit( rest_get_url_prefix() );

    这行代码调用了 rest_get_url_prefix() 函数,获取 REST API 的 URL 前缀。 默认情况下,这个前缀是 wp-json。 但是,你可以通过 rest_url_prefix 过滤器来修改这个前缀。 trailingslashit() 函数的作用是在前缀后面加上一个斜杠 /,确保前缀以斜杠结尾。 比如,如果 rest_get_url_prefix() 返回的是 wp-json,那么 $rest_prefix 的值就是 wp-json/

    让我们看看 rest_get_url_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 过滤器来修改这个字符串。

  4. 判断是否以 REST API 前缀开头:strpos()

    return ( strpos( $wp->request, $rest_prefix ) === 0 );

    最后,也是最关键的一步,它使用 strpos() 函数来判断 $wp->request 是否以 $rest_prefix 开头。 strpos() 函数的作用是在一个字符串中查找另一个字符串第一次出现的位置。 如果 $wp->request$rest_prefix 开头,那么 strpos() 函数会返回 0,因为 $rest_prefix 出现在 $wp->request 的起始位置。 如果 $wp->request 不以 $rest_prefix 开头,那么 strpos() 函数会返回一个大于 0 的整数,或者返回 false

    所以,( strpos( $wp->request, $rest_prefix ) === 0 ) 这个表达式的意思是:如果 $wp->request$rest_prefix 开头,那么就返回 true,否则返回 false

总结:is_rest_api_request() 的工作原理

简单来说,is_rest_api_request() 函数就是通过判断请求的URI是否以 REST API 的 URL 前缀开头来确定当前请求是否为 REST API 请求的。

第三步:实战演练,看看它怎么用

现在,我们已经知道了 is_rest_api_request() 函数的工作原理,接下来我们来看看它在实际开发中怎么用。

  1. 在插件或主题中使用

    你可以在你的插件或主题中使用 is_rest_api_request() 函数来判断当前请求是否为 REST API 请求,然后根据判断结果来执行不同的代码。

    if ( is_rest_api_request() ) {
        // 这是 REST API 请求
        // 执行 REST API 相关的代码
        add_action( 'rest_api_init', 'my_rest_api_endpoint' );
    } else {
        // 这不是 REST API 请求
        // 执行正常的 WordPress 代码
        add_action( 'wp_enqueue_scripts', 'my_theme_scripts' );
    }
  2. functions.php 中使用

    你也可以在你的主题的 functions.php 文件中使用 is_rest_api_request() 函数。

    function my_theme_setup() {
        if ( is_rest_api_request() ) {
            // 这是 REST API 请求
            // 执行 REST API 相关的代码
            add_action( 'rest_api_init', 'my_rest_api_endpoint' );
        } else {
            // 这不是 REST API 请求
            // 执行正常的 WordPress 代码
            add_action( 'wp_enqueue_scripts', 'my_theme_scripts' );
        }
    }
    add_action( 'after_setup_theme', 'my_theme_setup' );
  3. 结合其他函数使用

    is_rest_api_request() 函数可以和其他函数结合使用,来实现更复杂的逻辑。 比如,你可以结合 is_admin() 函数来判断当前请求是否为后台 REST API 请求。

    if ( is_rest_api_request() && is_admin() ) {
        // 这是后台 REST API 请求
        // 执行后台 REST API 相关的代码
        add_action( 'rest_api_init', 'my_admin_rest_api_endpoint' );
    }

第四步:注意事项和陷阱

在使用 is_rest_api_request() 函数的时候,有一些注意事项和陷阱需要注意。

  1. URL 前缀可能被修改

    正如我们前面提到的,REST API 的 URL 前缀可以通过 rest_url_prefix 过滤器来修改。 如果你修改了 URL 前缀,那么 is_rest_api_request() 函数的判断结果也会受到影响。

    所以,如果你修改了 URL 前缀,你需要确保你的代码能够正确地处理这种情况。 你可以使用 rest_get_url_prefix() 函数来获取当前的 URL 前缀,然后根据这个前缀来判断当前请求是否为 REST API 请求。

  2. 路由规则可能影响判断

    WordPress的路由规则可能会影响 is_rest_api_request() 函数的判断结果。 比如,如果你定义了一个自定义的路由规则,使得某个URL被映射到一个非REST API的页面,那么即使这个URL以 REST API 的 URL 前缀开头,is_rest_api_request() 函数也会返回 false

    所以,在定义自定义路由规则的时候,你需要注意不要和 REST API 的 URL 前缀冲突。

  3. init 钩子之前调用

    init 钩子之前调用 is_rest_api_request() 可能会导致不准确的结果。 这是因为 WordPress 在 init 钩子之后才会完全初始化 $wp 对象。 因此,最好在 init 钩子或之后的钩子中使用它。

第五步:高级用法和扩展

is_rest_api_request() 虽然简单,但它也为我们提供了一些高级用法和扩展的可能性。

  1. 自定义判断逻辑

    你可以通过自定义函数来扩展 is_rest_api_request() 函数的功能。 比如,你可以创建一个新的函数,用于判断当前请求是否为某个特定的 REST API 接口的请求。

    function is_my_rest_api_request() {
        if ( ! is_rest_api_request() ) {
            return false;
        }
    
        global $wp;
    
        if ( empty( $wp->request ) ) {
            return false;
        }
    
        return ( strpos( $wp->request, 'wp-json/my-plugin/v1/my-endpoint' ) === 0 );
    }
  2. 结合过滤器使用

    你可以结合 WordPress 的过滤器来修改 is_rest_api_request() 函数的返回值。 比如,你可以创建一个过滤器,用于在特定的情况下强制 is_rest_api_request() 函数返回 truefalse

    add_filter( 'is_rest_api_request', 'my_rest_api_request_filter', 10, 1 );
    
    function my_rest_api_request_filter( $is_rest_api_request ) {
        if ( $_GET['force_rest'] == 'true' ) {
            return true;
        }
    
        return $is_rest_api_request;
    }

    这个例子中,如果 URL 中包含了 force_rest=true 参数,那么 is_rest_api_request() 函数就会强制返回 true

总结:掌握 is_rest_api_request(),玩转 WordPress REST API

通过今天的讲解,相信大家对 is_rest_api_request() 函数已经有了深入的了解。 掌握了这个函数,你就可以更好地理解 WordPress 的 REST API 机制,并在开发插件或主题的时候更加得心应手。

希望今天的讲座对大家有所帮助。 记住,编程就像探险,不断学习,不断实践,才能发现更多的乐趣和惊喜。

表格总结:is_rest_api_request() 函数要点

特性 描述
定义位置 wp-includes/functions.php
功能 判断当前请求是否为 REST API 请求
工作原理 检查 $wp->request 是否以 rest_get_url_prefix() 返回的前缀开头
默认前缀 wp-json
前缀修改 可以通过 rest_url_prefix 过滤器修改
使用场景 在插件、主题的 functions.php 中,根据请求类型执行不同的代码
注意事项 URL 前缀可能被修改 路由规则可能影响判断 * 在 init 钩子之前调用可能导致不准确的结果
高级用法 自定义判断逻辑 结合过滤器使用

好了,今天的讲座就到这里。 感谢各位的收听! 祝大家编程愉快,bug 退散!

发表回复

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