[英]Prepare Wordpress Post Revision for Output in WP REST API
I built a custom endpoint for the WordPress REST API to get a post revision. 我为WordPress REST API构建了自定义终结点,以获取后期修订。 The result is in the Wordpress Post syntax: 结果使用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
Whereas the Wordpress REST API would provide me something like this: 而Wordpress REST API将为我提供以下信息:
"author": 1,
"title": {
"rendered": "My title"
},
"content": {
"rendered": "",
"protected": false
},
(one is printed via php the other is in a JSON format, but what is important is that in the first example it says: post_content
and in the second it's content
which is then separated in rendered
and protected
for example. (一个是通过php打印的,另一个是JSON格式的,但是重要的是在第一个示例中它说: post_content
,在第二个示例中它是content
,然后将其分离为例如rendered
和protected
。
I am pretty sure that it's almost the same thing as described here: https://wordpress.stackexchange.com/questions/236249/wp-api-v2-custom-endpoint-response-formatting?newreg=7edb54e1ae494e528e5e146982469664 我非常确定这几乎与此处所述相同: https : //wordpress.stackexchange.com/questions/236249/wp-api-v2-custom-endpoint-response-formatting?newreg=7edb54e1ae494e528e5e146982469664
But in my case I have revisions. 但就我而言,我有修改。
I tried to prepare the Post Object for the REST API. 我试图为REST API准备发布对象。 I created a new instance of the WP_REST_Revisions_Controller and tried to use its method prepare_item_for_response
. 我创建了WP_REST_Revisions_Controller的新实例,并尝试使用其方法prepare_item_for_response
。 $request ist a WP_Rest_Request. $ request和WP_Rest_Request。 (btw: why do I have to write new \\WP_REST_Revisions_Controller
with a backslash \\
before). (顺便说一句:为什么我必须new \\WP_REST_Revisions_Controller
用反斜杠\\
编写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);
The problem is that I get Notices: 问题是我收到通知:
<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>
....
Which must refer to these lines: https://developer.wordpress.org/reference/classes/wp_rest_revisions_controller/ (line 350 and following). 必须参考以下行: https : //developer.wordpress.org/reference/classes/wp_rest_revisions_controller/ (第350行及以下)。
After the notices I print the $response
and I get this: 发出通知后,我将打印$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
)
.. somehow the data is missing or something else went wrong. ..不知何故,数据丢失或其他原因出了问题。
And here is the whole php script to see what I am doing: 这是整个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();
I would be really glad to receive any hints for solving this problem. 收到解决该问题的任何提示,我将非常高兴。 Cheers 干杯
I haven't seen the result of your print_r
but I'm going to guess that it's an array of WP_Post
objects. 我还没有看到您的print_r
的结果,但是我猜想它是WP_Post
对象的数组。 prepare_item_for_response
requires a single WP_Post
as the first argument and you're passing it an array. prepare_item_for_response
需要一个WP_Post
作为第一个参数,并且您要向其传递一个数组。
Try this, after you set $latest_revision
: 设置$latest_revision
后,尝试以下$latest_revision
:
if (!is_array($latest_revision) || !count($latest_revision))
return null;
$latest_revision = array_values($latest_revision)[0];
The array_values
call is a quick and easy way to re-index your array. array_values
调用是重新索引数组的快速简便的方法。
This should give you a single post and not an array. 这应该给您一个帖子而不是一个数组。
Update: per your own answer to your question and the questions you asked. 更新:根据您自己对问题和所提问题的回答。
prepare_item_for_response
rewrites a WP_Post
object as something that can be serialized uniformly by the REST controller to output. prepare_item_for_response
将WP_Post
对象重写为WP_Post
REST控制器统一序列化以输出的对象。 For instance, it handles attachments rather than simply ignoring them. 例如,它处理附件而不是简单地忽略它们。 If you simply returned a WP_Post
object over, say, JSON, you'd miss out on a lot of the post content. 如果仅通过JSON返回WP_Post
对象,那么您将错过很多帖子内容。 You can think of prepare_response_for_collection
as the array version of the same thing. 您可以将prepare_response_for_collection
视为同一事物的数组版本。 Really, it's more like the WP_Query
version of the same thing so the WP rest controller can act as one-stop shopping to return lists of WP_Post
objects to a REST consumer. 实际上,它更像是同一事物的WP_Query
版本,因此WP rest控制器可以充当一站式购物,将WP_Post
对象的列表返回给REST使用者。
rest_ensure_response
does something similar for any REST response. rest_ensure_response
对任何 REST响应rest_ensure_response
执行类似的操作。 It hides the loose typing of PHP (and WP), where actions like function calls can return nothing or indeterminate things, from REST, where every request must have an appropriate response. 它隐藏了PHP(和WP)的松散类型,在这种类型中,函数调用之类的操作无法从REST返回任何内容或不确定的事情,而REST中的每个请求都必须具有适当的响应。 It's not much more than a wrapper that is aware of WP_Error
. 它只不过是知道WP_Error
的包装器WP_Error
。
I think I found a solution: Using $postController = new \\WP_REST_Revisions_Controller('revision');
我想我找到了一个解决方案:使用$postController = new \\WP_REST_Revisions_Controller('revision');
would not return a content field, so I had to use $postController = new \\WP_REST_Posts_Controller('post');
不会返回内容字段,所以我不得不使用$postController = new \\WP_REST_Posts_Controller('post');
although my result would actually be a 'revision'. 尽管我的结果实际上是“修订”。
Furthermore I used prepare_item_for_response
, prepare_response_for_collection
and rest_ensure_response
. 此外,我使用了prepare_item_for_response
, prepare_response_for_collection
和rest_ensure_response
。 Unfortunately I don't really know what these methods are actually doing...? 不幸的是,我真的不知道这些方法实际上在做什么……?
My new code: 我的新代码:
/**
* 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();
This gives me neat results like: 这给了我整洁的结果,例如:
{
"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.
If some feels like explaining what I did, I would be glad to read about it. 如果有些人想解释我的所作所为,那么我将很高兴读到它。 🤙🏼 🤙🏼
Cheers 干杯
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.