探究 WordPress `rest_get_all_endpoints()` 函数的源码:如何获取所有注册的 REST API 端点。

大家好,我是你们今天的WordPress REST API 端点探险向导。准备好了吗?我们要深入到 WordPress 的心脏,去扒一扒 rest_get_all_endpoints() 这个函数的底裤,看看它是如何把所有注册的 REST API 端点给“一网打尽”的。

第一站:认识一下我们的主角——rest_get_all_endpoints()

首先,我们要搞清楚 rest_get_all_endpoints() 到底是个什么角色。简单来说,它是一个 WordPress 函数,专门用来获取所有已注册的 REST API 端点。这就像一个餐厅的菜单,上面列着所有你可以点的菜(API 端点)。

这个函数定义在 wp-includes/rest-api.php 文件中。打开你的编辑器,找到它,我们一起看看它的真面目。

第二站:rest_get_all_endpoints() 源码解剖

/**
 * Gets all registered REST API routes.
 *
 * @since 4.4.0
 *
 * @return array List of registered routes, keyed by route.
 */
function rest_get_all_endpoints() {
    /** @var WP_REST_Server $wp_rest_server REST server instance. */
    global $wp_rest_server;

    if ( empty( $wp_rest_server ) ) {
        return array();
    }

    return $wp_rest_server->get_routes();
}

是不是很简单? 比想象的还简单?

  1. 注释说明: 函数开头通常会有注释,说明函数的作用、版本信息和返回值。
  2. 全局变量: 它使用了一个全局变量 $wp_rest_server。这个变量存储了 WP_REST_Server 类的实例,负责处理 REST API 请求。
  3. 空值检查: 检查 $wp_rest_server 是否为空。如果为空,说明 REST API 还没有初始化,直接返回一个空数组。
  4. 获取路由: 调用 $wp_rest_server 对象的 get_routes() 方法,获取所有已注册的路由。

所以,rest_get_all_endpoints() 本身只是一个“中间人”,它把获取路由的重任交给了 $wp_rest_server 对象的 get_routes() 方法。

第三站:深入 WP_REST_Serverget_routes() 方法

现在,我们要追根溯源,看看 WP_REST_Server 类的 get_routes() 方法是如何工作的。这个方法定义在 wp-includes/rest-api/class-wp-rest-server.php 文件中。

/**
 * Retrieves all registered routes.
 *
 * @return array Registered routes.
 */
public function get_routes() {
    return $this->endpoints;
}

更简单了! 这比你想象的还简单?!

get_routes() 方法直接返回了 $this->endpoints 属性。这个属性是一个数组,存储了所有已注册的路由信息。

第四站:$this->endpoints 从何而来?

关键问题来了:$this->endpoints 到底是在哪里被填充的?答案就在 WP_REST_Server 类的 register_route() 方法中。这个方法负责注册新的 REST API 路由。

我们来看看 register_route() 方法的简化版本:

/**
 * Registers a REST route.
 *
 * @param string             $namespace The namespace for the route.
 * @param string             $route     The route URI.
 * @param array              $args      Optional. An array of arguments for the route.
 */
public function register_route( $namespace, $route, $args = array() ) {
    $route = $this->normalize_route( $route );

    $defaults = array(
        'methods'              => 'GET',
        'callback'             => null,
        // ... 其他参数
    );
    $args = wp_parse_args( $args, $defaults );

    $full_route = $namespace . $route;

    // Store the route.
    $this->endpoints[ $full_route ] = $args;

    // ... 其他逻辑
}

可以看到,当调用 register_route() 方法注册一个新的路由时,会将路由信息存储到 $this->endpoints 数组中。

第五站:一个完整的例子

为了更好地理解,我们来看一个注册 REST API 端点的例子:

add_action( 'rest_api_init', function () {
    register_rest_route( 'myplugin/v1', '/authors', array(
        'methods'  => 'GET',
        'callback' => 'my_awesome_get_authors',
    ) );
} );

function my_awesome_get_authors( WP_REST_Request $request ) {
    // 获取作者数据
    $authors = get_users( array( 'role' => 'author' ) );

    // 将作者数据转换为 REST API 响应格式
    $data = array();
    foreach ( $authors as $author ) {
        $data[] = array(
            'id'    => $author->ID,
            'name'  => $author->display_name,
            'email' => $author->user_email,
        );
    }

    return rest_ensure_response( $data );
}

在这个例子中:

  1. add_action( 'rest_api_init', ... ):在 REST API 初始化时执行回调函数。
  2. register_rest_route( 'myplugin/v1', '/authors', ... ):注册一个新的 REST API 路由。
    • 'myplugin/v1':命名空间。
    • '/authors':路由。
    • 'methods' => 'GET':允许的 HTTP 方法。
    • 'callback' => 'my_awesome_get_authors':处理请求的回调函数。
  3. my_awesome_get_authors( WP_REST_Request $request ):回调函数,负责处理请求并返回数据。

当执行这段代码后,$wp_rest_server->endpoints 数组中就会包含 'myplugin/v1/authors' 这个键,对应的值就是注册路由时传入的参数数组。

第六站:如何使用 rest_get_all_endpoints() 获取端点信息

现在我们已经了解了 rest_get_all_endpoints() 的工作原理,接下来看看如何使用它来获取所有注册的 REST API 端点信息。

$endpoints = rest_get_all_endpoints();

if ( ! empty( $endpoints ) ) {
    echo "<pre>";
    print_r( $endpoints );
    echo "</pre>";
} else {
    echo "No REST API endpoints registered.";
}

这段代码会输出一个数组,其中包含了所有注册的 REST API 端点信息。

第七站:$endpoints 数组的结构

$endpoints 数组是一个多维数组,它的结构如下:

Array
(
    [route] => Array
        (
            [0] => Array
                (
                    'methods' => 'GET|POST|...',
                    'callback' => 'callable',
                    'args' => Array
                        (
                            [param1] => Array
                                (
                                    'validate_callback' => 'callable',
                                    'sanitize_callback' => 'callable',
                                    'required' => true|false,
                                    'default' => 'value',
                                ),
                            [param2] => ...
                        ),
                    'permission_callback' => 'callable',
                )
        )
)
  • route (string): REST API 端点的路由,例如 '/wp/v2/posts'
  • Array: 一个数组,包含一个或多个元素,每个元素代表一个针对该路由的处理方法。
    • methods (string): 允许的 HTTP 方法,例如 'GET', 'POST', 'PUT', 'DELETE' 等。多个方法用 | 分隔。
    • callback (callable): 处理请求的回调函数。
    • args (array): 参数定义,用于验证和过滤请求参数。
      • param1, param2, … (string): 参数名称。
      • validate_callback (callable): 验证参数的回调函数。
      • sanitize_callback (callable): 过滤参数的回调函数。
      • required (bool): 是否为必需参数。
      • default (mixed): 默认值。
    • permission_callback (callable): 权限验证的回调函数。

第八站:rest_get_server()函数

刚才我们提到了 $wp_rest_server 全局变量,但是如果我们想在没有全局变量作用域的地方使用REST服务器实例,可以使用 rest_get_server() 函数:

$server = rest_get_server();
$routes = $server->get_routes();

if ( ! empty( $routes ) ) {
    echo "<pre>";
    print_r( $routes );
    echo "</pre>";
} else {
    echo "No REST API endpoints registered.";
}

rest_get_server() 函数返回 $wp_rest_server 全局变量的值。

第九站:实战应用:生成 REST API 文档

现在我们已经掌握了 rest_get_all_endpoints() 的用法,可以利用它来做一些有趣的事情,比如生成 REST API 文档。

下面是一个简单的例子,演示如何生成一个 Markdown 格式的 REST API 文档:

function generate_rest_api_documentation() {
    $endpoints = rest_get_all_endpoints();

    $markdown = "# REST API Documentationnn";

    foreach ( $endpoints as $route => $handlers ) {
        $markdown .= "## " . $route . "nn";

        foreach ( $handlers as $handler ) {
            $methods = $handler['methods'];
            $callback = $handler['callback'];

            $markdown .= "- **Methods:** " . $methods . "n";
            $markdown .= "- **Callback:** " . (is_array($callback) ? get_class($callback[0]).'->'.$callback[1] : $callback) . "n";

            if ( ! empty( $handler['args'] ) ) {
                $markdown .= "- **Arguments:**n";
                foreach ( $handler['args'] as $arg_name => $arg_config ) {
                    $markdown .= "  - `" . $arg_name . "`:n";
                    if ( isset( $arg_config['required'] ) && $arg_config['required'] ) {
                        $markdown .= "    - **Required:** Yesn";
                    } else {
                        $markdown .= "    - **Required:** Non";
                    }
                    if ( isset( $arg_config['default'] ) ) {
                        $markdown .= "    - **Default:** `" . $arg_config['default'] . "`n";
                    }
                    // Add more argument details as needed
                }
            }

            $markdown .= "n";
        }
    }

    return $markdown;
}

// 使用示例
$documentation = generate_rest_api_documentation();
echo "<pre>";
echo htmlspecialchars($documentation); //为了安全转义
echo "</pre>";

这段代码会生成一个 Markdown 格式的文档,列出所有注册的 REST API 端点、允许的 HTTP 方法、回调函数和参数信息。 你可以将这段 Markdown 文本保存到文件中,然后使用 Markdown 编辑器打开,就可以看到漂亮的 REST API 文档了。

第十站:注意事项

  • 性能: rest_get_all_endpoints() 会返回所有已注册的 REST API 端点信息,如果你的 WordPress 站点有很多自定义的 REST API 端点,可能会影响性能。
  • 权限: REST API 端点通常会有权限验证,确保只有授权用户才能访问。在使用 rest_get_all_endpoints() 获取端点信息时,也要注意权限问题。
  • 缓存: 可以考虑对 rest_get_all_endpoints() 的结果进行缓存,以提高性能。

总结

今天我们一起深入探索了 WordPress 的 rest_get_all_endpoints() 函数,了解了它的工作原理、如何使用它来获取 REST API 端点信息,以及如何利用这些信息来生成 REST API 文档。希望这次探险之旅能帮助你更好地理解 WordPress REST API 的内部机制。

记住,理解代码最好的方式就是去阅读它,去实践它,去修改它。勇敢地去探索 WordPress 的源码吧! 祝你旅途愉快!

发表回复

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