我为WordPress REST API构建了一个自定义端点,以获得后期修订。结果是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();
我很高兴收到解决这个问题的任何提示。 干杯
答案 0 :(得分:1)
我没有看到你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
调用是一种快速简便的重新索引数组的方法。
这应该会给你一个帖子,而不是一个数组。
更新:根据您自己对问题的回答和您提出的问题。
prepare_item_for_response
将WP_Post
对象重写为REST控制器可以统一序列化输出的内容。例如,它处理附件而不是简单地忽略它们。如果您只是简单地返回一个WP_Post
对象,比如JSON,那么您将错过很多帖子内容。您可以将prepare_response_for_collection
视为同一事物的数组版本。实际上,它更像是同一事物的WP_Query
版本,因此WP休息控制器可以作为一站式购物,将WP_Post
对象列表返回给REST消费者。
rest_ensure_response
为任何 REST响应做了类似的事情。它隐藏了PHP(和WP)的松散类型,其中函数调用之类的操作可以从REST返回任何内容或不确定内容,其中每个请求必须具有适当的响应。它只不过是一个知道WP_Error
的包装器。
答案 1 :(得分:0)
我想我找到了一个解决方案:
使用$postController = new \WP_REST_Revisions_Controller('revision');
不会返回内容字段,因此我必须使用$postController = new \WP_REST_Posts_Controller('post');
,但我的结果实际上是“修订版”。
此外,我使用了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.
如果有人想解释我做了什么,我会很高兴看到它。
干杯