douna2014 2017-11-20 17:37
浏览 60
已采纳

为WP REST API中的输出准备Wordpress Post修订版

I built a custom endpoint for the WordPress REST API to get a post revision. The result is in the Wordpress Post syntax:

[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:

"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.

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

But in my case I have revisions.

I tried to prepare the Post Object for the REST API. I created a new instance of the WP_REST_Revisions_Controller and tried to use its method prepare_item_for_response. $request ist a WP_Rest_Request. (btw: why do I have to write new \WP_REST_Revisions_Controller with a backslash \ before).

$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).

After the notices I print the $response and I get this:

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

/**
 * 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

  • 写回答

2条回答 默认 最新

  • doubeng3412 2017-11-20 19:21
    关注

    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. prepare_item_for_response requires a single WP_Post as the first argument and you're passing it an array.

    Try this, after you set $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.

    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. 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. You can think of prepare_response_for_collection as the array version of the same thing. 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.

    rest_ensure_response does something similar for any REST 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. It's not much more than a wrapper that is aware of WP_Error.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥20 matlab yalmip kkt 双层优化问题
  • ¥15 如何在3D高斯飞溅的渲染的场景中获得一个可控的旋转物体
  • ¥88 实在没有想法,需要个思路
  • ¥15 MATLAB报错输入参数太多
  • ¥15 python中合并修改日期相同的CSV文件并按照修改日期的名字命名文件
  • ¥15 有赏,i卡绘世画不出
  • ¥15 如何用stata画出文献中常见的安慰剂检验图
  • ¥15 c语言链表结构体数据插入
  • ¥40 使用MATLAB解答线性代数问题
  • ¥15 COCOS的问题COCOS的问题