Я создал пользовательскую конечную точку для 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
Но в моем случае у меня есть исправления.
Я пытался подготовить объект Post для API REST.
Я создал новый экземпляр WP_REST_Revisions_Controller и попытался использовать его метод prepare_item_for_response
, $ request is 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
Вызов — это быстрый и простой способ переиндексировать ваш массив.
Это должно дать вам один пост, а не массив.
Обновить: за ваш собственный ответ на ваш вопрос и вопросы, которые вы задавали.
prepare_item_for_response
переписывает WP_Post
объект как нечто, что может быть равномерно сериализовано контроллером REST для вывода. Например, он обрабатывает вложения, а не просто игнорирует их. Если вы просто вернули WP_Post
возразите, скажем, на JSON, вы пропустите большую часть содержимого публикации. Вы можете думать о prepare_response_for_collection
как версия массива тоже самое. На самом деле, это больше похоже на WP_Query
версия того же самого, так что контроллер WP отдыха может выступать в качестве универсального покупок для возврата списков WP_Post
возражает против REST-потребителя.
rest_ensure_response
делает что-то подобное для любой ОТДЫХ ответ. Он скрывает свободную типизацию PHP (и WP), где такие действия, как вызовы функций, могут ничего не возвращать или ничего не определять, от REST, где каждый запрос должен иметь соответствующий ответ. Это не намного больше, чем обертка, которая знает WP_Error
,
Я думаю, что нашел решение:
С помощью $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.
Если кто-то захочет объяснить, что я сделал, я был бы рад прочитать об этом.
ура