函数文档

rest_preload_api_request()

💡 云策文档标注

概述

rest_preload_api_request() 是一个 WordPress REST API 函数,用于在页面预加载数据时,将内部请求的结果附加到 REST API 响应中。它通常作为 array_reduce 的回调函数使用,处理路径参数并返回修改后的累加器数组。

关键要点

  • 函数主要用于 REST API 数据预加载,优化页面性能。
  • 接受两个参数:$memo(累加器数组)和 $path(REST API 路径),支持字符串或数组形式指定路径和 HTTP 方法(GET 或 OPTIONS)。
  • 内部处理包括路径规范化、请求构建、响应处理,并应用 rest_post_dispatch 过滤器。
  • 返回一个数组,包含路径对应的响应数据和头部信息,结构根据方法类型(GET 或 OPTIONS)有所不同。

代码示例

function rest_preload_api_request( $memo, $path ) {
    // 函数实现代码,包括参数检查、路径处理、请求发送和响应存储。
    // 示例:如果 $path 是数组,解析方法和路径;否则默认使用 GET 方法。
    // 返回修改后的 $memo 数组,包含预加载数据。
}

注意事项

  • 该函数从 WordPress 5.0.0 版本开始引入,需确保环境兼容性。
  • 在 PHP 5.2 中,array_reduce 不支持数组参数,函数内部会进行兼容性处理。
  • 路径参数应避免尾部斜杠,函数使用 untrailingslashit() 进行清理。
  • 仅支持 GET 和 OPTIONS 方法,其他方法会自动回退到 GET。
  • 响应状态码必须为 200 才会被存储到累加器中。

📄 原文内容

Append result of internal request to REST API for purpose of preloading data to be attached to a page.

Description

Expected to be called in the context of array_reduce.

Parameters

$memoarrayrequired
Reduce accumulator.
$pathstringrequired
REST API path to preload.

Return

array Modified reduce accumulator.

Source

function rest_preload_api_request( $memo, $path ) {
	/*
	 * array_reduce() doesn't support passing an array in PHP 5.2,
	 * so we need to make sure we start with one.
	 */
	if ( ! is_array( $memo ) ) {
		$memo = array();
	}

	if ( empty( $path ) ) {
		return $memo;
	}

	$method = 'GET';
	if ( is_array( $path ) && 2 === count( $path ) ) {
		$method = end( $path );
		$path   = reset( $path );

		if ( ! in_array( $method, array( 'GET', 'OPTIONS' ), true ) ) {
			$method = 'GET';
		}
	}

	// Remove trailing slashes at the end of the REST API path (query part).
	$path = untrailingslashit( $path );
	if ( empty( $path ) ) {
		$path = '/';
	}

	$path_parts = parse_url( $path );
	if ( false === $path_parts ) {
		return $memo;
	}

	if ( isset( $path_parts['path'] ) && '/' !== $path_parts['path'] ) {
		// Remove trailing slashes from the "path" part of the REST API path.
		$path_parts['path'] = untrailingslashit( $path_parts['path'] );
		$path               = str_contains( $path, '?' ) ?
			$path_parts['path'] . '?' . ( $path_parts['query'] ?? '' ) :
			$path_parts['path'];
	}

	$request = new WP_REST_Request( $method, $path_parts['path'] );
	if ( ! empty( $path_parts['query'] ) ) {
		parse_str( $path_parts['query'], $query_params );
		$request->set_query_params( $query_params );
	}

	$response = rest_do_request( $request );
	if ( 200 === $response->status ) {
		$server = rest_get_server();
		/** This filter is documented in wp-includes/rest-api/class-wp-rest-server.php */
		$response = apply_filters( 'rest_post_dispatch', rest_ensure_response( $response ), $server, $request );
		$embed    = $request->has_param( '_embed' ) ? rest_parse_embed_param( $request['_embed'] ) : false;
		$data     = (array) $server->response_to_data( $response, $embed );

		if ( 'OPTIONS' === $method ) {
			$memo[ $method ][ $path ] = array(
				'body'    => $data,
				'headers' => $response->headers,
			);
		} else {
			$memo[ $path ] = array(
				'body'    => $data,
				'headers' => $response->headers,
			);
		}
	}

	return $memo;
}

Hooks

apply_filters( ‘rest_post_dispatch’, WP_HTTP_Response $result, WP_REST_Server $server, WP_REST_Request $request )

Filters the REST API response.

Changelog

Version Description
5.0.0 Introduced.