WordPress 5.6引入了一個框架,該框架可在對服務(wù)器的一個請求中進(jìn)行一系列REST API調(diào)用。簡單地說,當(dāng)需要進(jìn)行大量的寫操作時,這對性能優(yōu)化很有幫助。它還可以選擇提供基本的并發(fā)控制。

注冊
為了在批處理請求中使用,路由必須在注冊過程中首先聲明對功能的支持。例如下方代碼的第5行:
register_rest_route( 'my-ns/v1', 'my-route', array(
'methods' => WP_REST_Server::CREATABLE,
'callback' => 'my_callback',
'permission_callback' => 'my_permission_callback',
'allow_batch' => array( 'v1' => true ),
) );
如果REST API路由是使用最佳實(shí)踐實(shí)現(xiàn)的,則聲明支持應(yīng)足以使該路由可通過批處理端點(diǎn)寫入。具體來說,這些是要注意的事情:
- 路由必須使用該
WP_REST_Request對象來獲取所有請求數(shù)據(jù)。換句話說,它不應(yīng)該訪問$_GET,$_POST或$_SERVER變量得到參數(shù)或頭。 - 路線必須返回數(shù)據(jù)。這可以是一個
WP_REST_Response對象,一個WP_Error對象或任何類型的JSON可序列化數(shù)據(jù)。這意味著路由一定不能直接回顯響應(yīng)和die()。例如,使用wp_send_json()或wp_die()。 - 路線必須是可重入的。準(zhǔn)備好同一批路由被多次調(diào)用。
發(fā)出請求
要發(fā)送批處理,發(fā)送一個POST請求到?https://yoursite.test/wp-json/batch/v1使用所需的請求數(shù)組。例如,最簡單的批處理請求如下所示。
{
"requests": [
{
"path": "/my-ns/v1/route"
}
]
}
請求格式
每個請求都是一個可以接受以下屬性的對象。
{
"method": "PUT",
"path": "/my-ns/v1/route/1?query=param",
"headers": {
"My-Header": "my-value",
"Multi": [ "v1", "v2" ]
},
"body": {
"project": "Gutenberg"
}
}
method是用于請求的HTTP方法。如果省略,則使用POST方法。path是要調(diào)用的REST API路由。可以包含查詢參數(shù)。此屬性是必需的。headers是標(biāo)頭名稱到標(biāo)頭值的對象。如果標(biāo)頭具有多個值,則可以將其作為數(shù)組傳遞。body是傳遞給路線的參數(shù)。填寫POST參數(shù)類型。
發(fā)現(xiàn)最大請求
默認(rèn)情況下,REST API在一個批次中最多接受25個請求。但是,此值是可過濾的,因此可以根據(jù)服務(wù)器資源按比例放大或縮小。
function my_prefix_rest_get_max_batch_size() {
return 50;
}
add_filter( 'rest_get_max_batch_size', 'my_prefix_rest_get_max_batch_size' );
因此,強(qiáng)烈建議客戶提出請求前要求以發(fā)現(xiàn)限制。例如,發(fā)出OPTIONS請求到batch/v1將返回以下響應(yīng)。
{
"namespace": "",
"methods": [ "POST" ],
"endpoints": [
{
"methods": [ "POST" ],
"args": {
"validation": {
"type": "string",
"enum": [ "require-all-validate", "normal" ],
"default": "normal",
"required": false
},
"requests": {
"type": "array",
"maxItems": 25,
"items": {
"type": "object",
"properties": {
"method": {
"type": "string",
"enum": [ "POST", "PUT", "PATCH", "DELETE" ],
"default": "POST"
},
"path": {
"type": "string",
"required": true
},
"body": {
"type": "object",
"properties": [],
"additionalProperties": true
},
"headers": {
"type": "object",
"properties": [],
"additionalProperties": {
"type": [ "string", "array" ],
"items": {
"type": "string"
}
}
}
}
},
"required": true
}
}
}
],
"_links": {
"self": [
{
"href": "http://trunk.test/wp-json/batch/v1"
}
]
}
}
該限制在endpoints[0].args.requests.maxItems屬性中指定。
回應(yīng)格式
批處理端點(diǎn)將以與請求相同的順序返回207狀態(tài)碼和每個請求的響應(yīng)。例如:
{
"responses": [
{
"body": {
"id": 1,
"_links": {
"self": [
{
"href": "http://trunk.test/wp-json/my-ns/v1/route/1"
}
]
}
},
"status": 201,
"headers": {
"Location": "http://trunk.test/wp-json/my-n1/v1/route/1",
"Allow": "GET, POST"
}
}
]
}
在內(nèi)部,REST API信封包括它中之前每個響應(yīng)responses陣列。
驗證方式
默認(rèn)情況下,每個請求都是獨(dú)立處理的。這意味著批處理響應(yīng)可以包含一些成功的請求和一些失敗的請求。有時希望僅在所有請求均有效的情況下處理批處理。例如,在古騰堡(Gutenberg),我們不想保存某些菜單項,理想情況下將保存所有菜單項,或者不保存任何菜單項。
為此,REST API允許傳遞的validation模式require-all-validate。設(shè)置此選項后,REST API將根據(jù)WP_REST_Request::has_valid_params()和WP_REST_Request::sanitize_params()首先檢查每個請求是否有效。如果有任何請求未通過驗證,則整個批次都將被拒絕。
在此示例中,發(fā)出了兩個請求的批處理,第二個請求驗證失敗。由于responses的順序仍與requests的順序相同,因此用null表示請求未通過驗證。
{
"failed": "validation",
"responses": [
null,
{
"body": {
"code": "error_code",
"message": "Invalid request data",
"data": { "status": 400 }
},
"status": 400,
"headers": {}
}
]
}
注意:使用require-all-validate不能保證所有請求都會成功。路由回調(diào)仍可能返回錯誤。
驗證回調(diào)
在注冊路由時,這些WP_REST_Request方法使用validate_callback和sanitize_callback為每個參數(shù)指定。在大多數(shù)情況下,這將意味著基于架構(gòu)的驗證。
路線內(nèi)部完成的任何驗證(例如在prepare_item_for_database方法中)都不會導(dǎo)致批次被拒絕。如果這是一個令人擔(dān)憂的問題,建議將盡可能多的驗證移到validate_callback每個單獨(dú)的參數(shù)中。例如,這可以建立在基于現(xiàn)有架構(gòu)的驗證之上。
'post' => array(
'type' => 'integer',
'minimum' => 1,
'required' => true,
'arg_options' => array(
'validate_callback' => function ( $value, $request, $param ) {
$valid = rest_validate_request_arg( $value, $request, $param );
if ( is_wp_error( $valid ) ) {
return $valid;
}
if ( ! get_post( $value ) || ! current_user_can( 'read_post', $value ) ) {
return new WP_Error( 'invalid_post', __( 'That post does not exist.' ) );
}
return true;
}
)
)
有時在執(zhí)行驗證時,需要請求的完整上下文。通常,此驗證將在prepare_item_for_database中完成,但WordPress 5.6引入了替代方法。注冊路線時,現(xiàn)在可以指定validate_callback頂層。它將接收完整的WP_REST_Request對象,并可以返回WP_Error實(shí)例或false。如果參數(shù)級驗證未成功,則不會執(zhí)行該回調(diào)。
register_rest_route( 'my-ns/v1', 'route', array(
'callback' => '__return_empty_array',
'permission_callback' => '__return_true',
'validate_callback' => function( $request ) {
if ( $request['pass1'] !== $request['pass2'] ) {
return new WP_Error(
'passwords_must_match',
__( 'Passwords must match.' ),
array( 'status' => 400 )
);
}
return true;
}
) );
注意:請求驗證在權(quán)限檢查之前進(jìn)行。在考慮是否將邏輯移至validate_callback時要牢記這一點(diǎn)。
局限性
當(dāng)前沒有內(nèi)置路由允許批處理。這將在將來的版本中添加,最有可能立即從WordPress 5.7開始。
不支持GET?請求。相反,鼓勵開發(fā)人員暫時使用鏈接和嵌入或利用并行請求。
進(jìn)一步閱讀
參見#50244,[49252],[48947],[48945]。




