为 WP REST API 中的输出准备 Wordpress Post 修订版
Prepare Wordpress Post Revision for Output in WP REST API
我为 WordPress REST API 构建了一个自定义端点以获得 post 修订。结果在 Wordpress Post 语法中:
[ID] => 478
[post_author] => 1
[post_date] => 2017-11-20 17:22:11
[post_date_gmt] => 2017-11-20 16:22:11
[post_content] => My Post content
而 Wordpress REST API 会给我这样的东西:
"author": 1,
"title": {
"rendered": "My title"
},
"content": {
"rendered": "",
"protected": false
},
(一个是通过 php 打印的,另一个是 JSON 格式,但重要的是在第一个例子中它说: post_content
而在第二个例子中它是例如 content
然后在 rendered
和 protected
中分开。
我很确定它与此处描述的几乎相同:
https://wordpress.stackexchange.com/questions/236249/wp-api-v2-custom-endpoint-response-formatting?newreg=7edb54e1ae494e528e5e146982469664
但就我而言,我有修改。
我试图为 REST API 准备 Post 对象。
我创建了一个 WP_REST_Revisions_Controller 的新实例并尝试使用它的方法 prepare_item_for_response
。 $request 是 WP_Rest_Request。 (顺便说一句:为什么我必须在 new \WP_REST_Revisions_Controller
之前写一个反斜杠 \
)。
$latest_revision = wp_get_post_revisions( $id, $args ); //WP Post Object
$postController = new \WP_REST_Revisions_Controller('revision');
$response = $postController->prepare_item_for_response( $latest_revision, $request );
print_r($response);
问题是我收到通知:
<b>Notice</b>: Trying to get property of non-object in <b>/Users/USER/Documents/my-api/wp/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php</b> on line <b>350</b>
<b>Notice</b>: Trying to get property of non-object in <b>/Users/USER/Documents/my-api/wp/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php</b> on line <b>354</b>
<b>Notice</b>: Trying to get property of non-object in <b>/Users/USER/Documents/my-api/wp/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php</b> on line <b>354</b>
....
其中必须引用这些行:
https://developer.wordpress.org/reference/classes/wp_rest_revisions_controller/(第 350 行及以下)。
在我打印 $response
通知后,我得到了这个:
WP_REST_Response Object
(
[links:protected] => Array
(
)
[matched_route:protected] =>
[matched_handler:protected] =>
[data] => Array
(
[author] => 0
[date] =>
[date_gmt] =>
[id] =>
[modified] =>
[modified_gmt] =>
[parent] => 0
[slug] =>
[guid] => Array
(
[rendered] =>
[raw] =>
)
)
[headers] => Array
(
)
[status] => 200
)
..不知何故数据丢失或其他错误。
这里是整个 php 脚本,看看我在做什么:
<?php
/**
* Add a new API route for a post or pages preview
*/
class Preview_To_REST_API_Controller extends WP_REST_Controller {
//The namespace and version for the REST SERVER
var $namespace = 'previews/v';
var $version = '1';
public function register_routes() {
$namespace = $this->namespace . $this->version;
$base = 'preview';
register_rest_route( $namespace, '/' . $base, array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_preview' ),
'permission_callback' => array( $this, 'get_permission' )
)
) );
}
// Register our REST Server
public function hook_rest_server(){
add_action( 'rest_api_init', array( $this, 'register_routes' ) );
}
public function get_permission(){
if ( ! current_user_can( 'edit_posts' ) ) {
return new WP_Error( 'rest_forbidden', esc_html__( 'You do not have permissions to view this data.', 'my-text-domain' ), array( 'status' => 401 ) );
}
// This approach blocks the endpoint operation. You could alternatively do this by an un-blocking approach, by returning false here and changing the permissions check.
return true;
}
public function get_preview( WP_REST_Request $request ){
// use the helper methods to get the parameters
$id = $request->get_param( 'id' );
// Only return the newest
$args = array (
'order' => 'DESC',
'orderby' => 'date',
'posts_per_page' => '1'
);
// Preview version is saved in the latest revision of the page/post
$latest_revision = wp_get_post_revisions( $id, $args );
print_r($latest_revision);
$postController = new \WP_REST_Revisions_Controller('revision');
$response = $postController->prepare_item_for_response( $latest_revision, $request );
print_r($response);
if ($latest_revision) {
// Use the current method to get the only element in the revisions array
// [0] does not return anything, because the Array's value is saved
// as the ID key: Array[$id], but this ID we need to find out first
$revision_id = current($latest_revision) -> ID;
$acf_fields = get_fields($revision_id);
if ( empty($latest_revision) ) {
return null;
}
// Add acf fields to latest revision
$latest_revision[$revision_id] -> acf = $acf_fields;
return $latest_revision;
} else {
return null;
}
}
}
$preview_controller = new Preview_To_REST_API_Controller();
$preview_controller->hook_rest_server();
如果能收到解决此问题的任何提示,我将非常高兴。
干杯
我还没有看到你的 print_r
的结果,但我猜它是一个 WP_Post
对象的数组。 prepare_item_for_response
需要一个 WP_Post
作为第一个参数,您要将它传递给一个数组。
设置 $latest_revision
后试试这个:
if (!is_array($latest_revision) || !count($latest_revision))
return null;
$latest_revision = array_values($latest_revision)[0];
array_values
调用是重新索引数组的一种快速简便的方法。
这应该给你一个 post 而不是一个数组。
更新: 根据你自己对问题的回答和你提出的问题。
prepare_item_for_response
将一个WP_Post
对象重写为可以被REST控制器统一序列化输出的东西。例如,它处理附件而不是简单地忽略它们。如果您只是 return 编辑一个 WP_Post
对象,比如说 JSON,您会错过很多 post 内容。您可以将 prepare_response_for_collection
视为同一事物的数组版本。真的,它更像是同一事物的 WP_Query
版本,因此 WP rest 控制器可以作为一站式购物,向 REST 消费者提供 return WP_Post
对象列表。
rest_ensure_response
对 any REST 响应做了类似的事情。它隐藏了 PHP(和 WP)的松散类型,其中像函数调用这样的操作可以 return 没有或不确定的东西,来自 REST,其中每个请求 必须 适当的回应。它只不过是一个知道 WP_Error
.
的包装器
我想我找到了解决办法:
使用 $postController = new \WP_REST_Revisions_Controller('revision');
不会 return 内容字段,所以我不得不使用 $postController = new \WP_REST_Posts_Controller('post');
尽管我的结果实际上是 'revision'.
此外,我使用了prepare_item_for_response
、prepare_response_for_collection
和rest_ensure_response
。不幸的是,我真的不知道这些方法实际上在做什么......?
我的新密码:
/**
* Add a new API route for a post or pages preview
*/
class Preview_To_REST_API_Controller extends WP_REST_Controller {
//The namespace and version for the REST SERVER
var $namespace = 'previews/v';
var $version = '1';
public function register_routes() {
$namespace = $this->namespace . $this->version;
$base = 'preview';
register_rest_route( $namespace, '/' . $base, array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_preview' ),
'permission_callback' => array( $this, 'get_permission' )
)
) );
}
// Register our REST Server
public function hook_rest_server(){
add_action( 'rest_api_init', array( $this, 'register_routes' ) );
}
public function get_permission(){
if ( ! current_user_can( 'edit_posts' ) ) {
return new WP_Error( 'rest_forbidden', esc_html__( 'You do not have permissions to view this data.', 'my-text-domain' ), array( 'status' => 401 ) );
}
// This approach blocks the endpoint operation. You could alternatively do this by an un-blocking approach, by returning false here and changing the permissions check.
return true;
}
public function get_preview( WP_REST_Request $request ){
// use the helper methods to get the parameters
$id = $request->get_param( 'id' );
// Only return the newest
$args = array (
'order' => 'DESC',
'orderby' => 'date',
'posts_per_page' => '1'
);
// Preview version is saved in the latest revision of the page/post
$latest_revision = wp_get_post_revisions( $id, $args );
if (!is_array($latest_revision) || !count($latest_revision)){
return null;
}
$latest_revision = array_values($latest_revision)[0];
$postController = new \WP_REST_Posts_Controller('post');
$response = $postController->prepare_item_for_response( $latest_revision, $request );
$data = $postController->prepare_response_for_collection( $response );
if ($latest_revision) {
// Use the current method to get the only element in the revisions array
// [0] does not return anything, because the Array's value is saved
// as the ID key: Array[$id], but this ID we need to find out first
$revision_id = $latest_revision -> ID;
$acf_fields = get_fields($revision_id);
if ( empty($latest_revision) ) {
return null;
}
// Add acf fields to latest revision
$data['acf'] = $acf_fields;
return rest_ensure_response($data);
} else {
return null;
}
}
}
$preview_controller = new Preview_To_REST_API_Controller();
$preview_controller->hook_rest_server();
这给了我整洁的结果,如:
{
"id": 478,
"date": "2017-11-20T23:51:10",
"date_gmt": "2017-11-20T22:51:10",
"guid": {
"rendered": "http://localhost:3000/51-autosave-v1/"
},
"modified": "2017-11-20T23:51:10",
"modified_gmt": "2017-11-20T22:51:10",
"slug": "51-autosave-v1",
"status": "inherit",
"type": "revision",
"link": "http://localhost:3000/51-autosave-v1/",
"title": {
"rendered": "my title"
},
"content": {
"rendered": "",
"protected": false
},
"excerpt": {
"rendered": "",
"protected": false
},
"author": 1,
"featured_media": 0,
"comment_status": "closed",
"ping_status": "closed",
"sticky": false,
"template": "", ... etc.
如果有人想解释一下我的所作所为,我很乐意阅读。
干杯
我为 WordPress REST API 构建了一个自定义端点以获得 post 修订。结果在 Wordpress Post 语法中:
[ID] => 478
[post_author] => 1
[post_date] => 2017-11-20 17:22:11
[post_date_gmt] => 2017-11-20 16:22:11
[post_content] => My Post content
而 Wordpress REST API 会给我这样的东西:
"author": 1,
"title": {
"rendered": "My title"
},
"content": {
"rendered": "",
"protected": false
},
(一个是通过 php 打印的,另一个是 JSON 格式,但重要的是在第一个例子中它说: post_content
而在第二个例子中它是例如 content
然后在 rendered
和 protected
中分开。
我很确定它与此处描述的几乎相同: https://wordpress.stackexchange.com/questions/236249/wp-api-v2-custom-endpoint-response-formatting?newreg=7edb54e1ae494e528e5e146982469664
但就我而言,我有修改。
我试图为 REST API 准备 Post 对象。
我创建了一个 WP_REST_Revisions_Controller 的新实例并尝试使用它的方法 prepare_item_for_response
。 $request 是 WP_Rest_Request。 (顺便说一句:为什么我必须在 new \WP_REST_Revisions_Controller
之前写一个反斜杠 \
)。
$latest_revision = wp_get_post_revisions( $id, $args ); //WP Post Object
$postController = new \WP_REST_Revisions_Controller('revision');
$response = $postController->prepare_item_for_response( $latest_revision, $request );
print_r($response);
问题是我收到通知:
<b>Notice</b>: Trying to get property of non-object in <b>/Users/USER/Documents/my-api/wp/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php</b> on line <b>350</b>
<b>Notice</b>: Trying to get property of non-object in <b>/Users/USER/Documents/my-api/wp/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php</b> on line <b>354</b>
<b>Notice</b>: Trying to get property of non-object in <b>/Users/USER/Documents/my-api/wp/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php</b> on line <b>354</b>
....
其中必须引用这些行: https://developer.wordpress.org/reference/classes/wp_rest_revisions_controller/(第 350 行及以下)。
在我打印 $response
通知后,我得到了这个:
WP_REST_Response Object
(
[links:protected] => Array
(
)
[matched_route:protected] =>
[matched_handler:protected] =>
[data] => Array
(
[author] => 0
[date] =>
[date_gmt] =>
[id] =>
[modified] =>
[modified_gmt] =>
[parent] => 0
[slug] =>
[guid] => Array
(
[rendered] =>
[raw] =>
)
)
[headers] => Array
(
)
[status] => 200
)
..不知何故数据丢失或其他错误。
这里是整个 php 脚本,看看我在做什么:
<?php
/**
* Add a new API route for a post or pages preview
*/
class Preview_To_REST_API_Controller extends WP_REST_Controller {
//The namespace and version for the REST SERVER
var $namespace = 'previews/v';
var $version = '1';
public function register_routes() {
$namespace = $this->namespace . $this->version;
$base = 'preview';
register_rest_route( $namespace, '/' . $base, array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_preview' ),
'permission_callback' => array( $this, 'get_permission' )
)
) );
}
// Register our REST Server
public function hook_rest_server(){
add_action( 'rest_api_init', array( $this, 'register_routes' ) );
}
public function get_permission(){
if ( ! current_user_can( 'edit_posts' ) ) {
return new WP_Error( 'rest_forbidden', esc_html__( 'You do not have permissions to view this data.', 'my-text-domain' ), array( 'status' => 401 ) );
}
// This approach blocks the endpoint operation. You could alternatively do this by an un-blocking approach, by returning false here and changing the permissions check.
return true;
}
public function get_preview( WP_REST_Request $request ){
// use the helper methods to get the parameters
$id = $request->get_param( 'id' );
// Only return the newest
$args = array (
'order' => 'DESC',
'orderby' => 'date',
'posts_per_page' => '1'
);
// Preview version is saved in the latest revision of the page/post
$latest_revision = wp_get_post_revisions( $id, $args );
print_r($latest_revision);
$postController = new \WP_REST_Revisions_Controller('revision');
$response = $postController->prepare_item_for_response( $latest_revision, $request );
print_r($response);
if ($latest_revision) {
// Use the current method to get the only element in the revisions array
// [0] does not return anything, because the Array's value is saved
// as the ID key: Array[$id], but this ID we need to find out first
$revision_id = current($latest_revision) -> ID;
$acf_fields = get_fields($revision_id);
if ( empty($latest_revision) ) {
return null;
}
// Add acf fields to latest revision
$latest_revision[$revision_id] -> acf = $acf_fields;
return $latest_revision;
} else {
return null;
}
}
}
$preview_controller = new Preview_To_REST_API_Controller();
$preview_controller->hook_rest_server();
如果能收到解决此问题的任何提示,我将非常高兴。 干杯
我还没有看到你的 print_r
的结果,但我猜它是一个 WP_Post
对象的数组。 prepare_item_for_response
需要一个 WP_Post
作为第一个参数,您要将它传递给一个数组。
设置 $latest_revision
后试试这个:
if (!is_array($latest_revision) || !count($latest_revision))
return null;
$latest_revision = array_values($latest_revision)[0];
array_values
调用是重新索引数组的一种快速简便的方法。
这应该给你一个 post 而不是一个数组。
更新: 根据你自己对问题的回答和你提出的问题。
prepare_item_for_response
将一个WP_Post
对象重写为可以被REST控制器统一序列化输出的东西。例如,它处理附件而不是简单地忽略它们。如果您只是 return 编辑一个 WP_Post
对象,比如说 JSON,您会错过很多 post 内容。您可以将 prepare_response_for_collection
视为同一事物的数组版本。真的,它更像是同一事物的 WP_Query
版本,因此 WP rest 控制器可以作为一站式购物,向 REST 消费者提供 return WP_Post
对象列表。
rest_ensure_response
对 any REST 响应做了类似的事情。它隐藏了 PHP(和 WP)的松散类型,其中像函数调用这样的操作可以 return 没有或不确定的东西,来自 REST,其中每个请求 必须 适当的回应。它只不过是一个知道 WP_Error
.
我想我找到了解决办法:
使用 $postController = new \WP_REST_Revisions_Controller('revision');
不会 return 内容字段,所以我不得不使用 $postController = new \WP_REST_Posts_Controller('post');
尽管我的结果实际上是 'revision'.
此外,我使用了prepare_item_for_response
、prepare_response_for_collection
和rest_ensure_response
。不幸的是,我真的不知道这些方法实际上在做什么......?
我的新密码:
/**
* Add a new API route for a post or pages preview
*/
class Preview_To_REST_API_Controller extends WP_REST_Controller {
//The namespace and version for the REST SERVER
var $namespace = 'previews/v';
var $version = '1';
public function register_routes() {
$namespace = $this->namespace . $this->version;
$base = 'preview';
register_rest_route( $namespace, '/' . $base, array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_preview' ),
'permission_callback' => array( $this, 'get_permission' )
)
) );
}
// Register our REST Server
public function hook_rest_server(){
add_action( 'rest_api_init', array( $this, 'register_routes' ) );
}
public function get_permission(){
if ( ! current_user_can( 'edit_posts' ) ) {
return new WP_Error( 'rest_forbidden', esc_html__( 'You do not have permissions to view this data.', 'my-text-domain' ), array( 'status' => 401 ) );
}
// This approach blocks the endpoint operation. You could alternatively do this by an un-blocking approach, by returning false here and changing the permissions check.
return true;
}
public function get_preview( WP_REST_Request $request ){
// use the helper methods to get the parameters
$id = $request->get_param( 'id' );
// Only return the newest
$args = array (
'order' => 'DESC',
'orderby' => 'date',
'posts_per_page' => '1'
);
// Preview version is saved in the latest revision of the page/post
$latest_revision = wp_get_post_revisions( $id, $args );
if (!is_array($latest_revision) || !count($latest_revision)){
return null;
}
$latest_revision = array_values($latest_revision)[0];
$postController = new \WP_REST_Posts_Controller('post');
$response = $postController->prepare_item_for_response( $latest_revision, $request );
$data = $postController->prepare_response_for_collection( $response );
if ($latest_revision) {
// Use the current method to get the only element in the revisions array
// [0] does not return anything, because the Array's value is saved
// as the ID key: Array[$id], but this ID we need to find out first
$revision_id = $latest_revision -> ID;
$acf_fields = get_fields($revision_id);
if ( empty($latest_revision) ) {
return null;
}
// Add acf fields to latest revision
$data['acf'] = $acf_fields;
return rest_ensure_response($data);
} else {
return null;
}
}
}
$preview_controller = new Preview_To_REST_API_Controller();
$preview_controller->hook_rest_server();
这给了我整洁的结果,如:
{
"id": 478,
"date": "2017-11-20T23:51:10",
"date_gmt": "2017-11-20T22:51:10",
"guid": {
"rendered": "http://localhost:3000/51-autosave-v1/"
},
"modified": "2017-11-20T23:51:10",
"modified_gmt": "2017-11-20T22:51:10",
"slug": "51-autosave-v1",
"status": "inherit",
"type": "revision",
"link": "http://localhost:3000/51-autosave-v1/",
"title": {
"rendered": "my title"
},
"content": {
"rendered": "",
"protected": false
},
"excerpt": {
"rendered": "",
"protected": false
},
"author": 1,
"featured_media": 0,
"comment_status": "closed",
"ping_status": "closed",
"sticky": false,
"template": "", ... etc.
如果有人想解释一下我的所作所为,我很乐意阅读。
干杯