plaglamist
plaglamist

Reputation: 53

Custom endpoint and X-WP-TotalPages (headers) headers are null

I created custom endpoint for products, now im geting my products from Wp Rest Api (/wp-json/wl/v1/products) and everything goes nice, my problem is that my custom endpoint or route(whatever) doesnt return headers like (X-WP-Total, X-WP-TotalPages - im getting null) that i need for pagination, actually ive found the ansewer here https://wordpress.stackexchange.com/questions/270005/custom-endpoint-and-x-wp-totalpages-headers

but i dont know where i shold put that php code, becouse i`m using the WP_REST_Controller class and i a little bit confused with placing of php code, please help me to know =)

$response  = rest_ensure_response( $posts );

$response->header( 'X-WP-Total', (int) $total_posts );
$response->header( 'X-WP-TotalPages', (int) $max_pages );

return $response;

where:

$total_posts = $posts_query->found_posts;
$max_pages = $posts_query->max_num_pages;

so what i have the solution

$total_posts = $posts_query->found_posts;
$max_pages = $posts_query->max_num_pages;
$response  = rest_ensure_response( $posts );
$response->header( 'X-WP-Total', (int) $total_posts );
$response->header( 'X-WP-TotalPages', (int) $max_pages );

return $response;

and my Wp rest controller class

<?php
/**
 * Plugin Name: Custom API Plugin
 * Description: That plugin creates some custom end points for wp-admin
 * Author: Ahma
 * Version: 1
 */

add_action( 'rest_api_init', 'prefix_register_my_rest_routes' );
function prefix_register_my_rest_routes() {
    $controller = new My_REST_Posts_Controller();
    $controller->register_routes();
}

class My_REST_Posts_Controller extends WP_REST_Controller {

    function __construct(){
        $this->namespace = 'wl/v1';
        $this->rest_base = 'products';
    }

    function register_routes(){

        register_rest_route( $this->namespace, "/$this->rest_base", [
            [
                'methods'             => 'GET',
                'callback'            => [ $this, 'get_items' ],
            ],
            'schema' => [ $this, 'get_item_schema' ],
        ] );

        register_rest_route( $this->namespace, "/$this->rest_base/(?P<id>[\w]+)", [
            [
                'methods'   => 'GET',
                'callback'  => [ $this, 'get_item' ],
            ],
            'schema' => [ $this, 'get_item_schema' ],
        ] );
    }


    /**
     * Получает последние посты и отдает их в виде rest ответа.
     *
     * @param WP_REST_Request $request Текущий запрос.
     *
     * @return WP_Error|array
     */
    function get_items($request ){
        $data = [];

        $posts = get_posts( array(
            'post_per_page' => 3,
            'orderby'     => 'date',
            'order'       => 'DESC',
            'post_type'   => 'products',
        ));

        if ( empty( $posts ) )
            return $data;
        
        foreach( $posts as $post ){
            $response = $this->prepare_item_for_response( $post, $request );
            $data[] = $this->prepare_response_for_collection( $response );
             
        }
        

        return $data;
    }

    /**
     * Получает отдельный ресурс.
     *
     * @param WP_REST_Request $request Текущий запрос.
     *
     * @return array
     */
    function get_item( $request ){
        $id = (int) $request['id'];
        $post = get_post( $id );

        if( ! $post )
            return array();

        return $this->prepare_item_for_response( $post, $request );
    }

    /**
     * Собирает данные ресурса в соответствии со схемой ресурса.
     *
     * @param WP_Post         $post    Объект ресурса, из которого будут взяты оригинальные данные.
     * @param WP_REST_Request $request Текущий запрос.
     *
     * @return array
     */
    function prepare_item_for_response( $post, $request ){

        $post_data = [];

        $schema = $this->get_item_schema();

        // We are also renaming the fields to more understandable names.
        if ( isset( $schema['properties']['id'] ) )
            $post_data['id'] = (int) $post->ID;

        if ( isset( $schema['properties']['title'] ) )
            $post_data['title'] = apply_filters( 'the_title', $post->post_title, $post );

        if ( isset( $schema['properties']['content'] ) )
            $post_data['content'] = apply_filters( 'the_content', $post->post_content, $post );

        if ( isset( $schema['properties']['featured_image'] ) )
            $post_data['featured_image'] = get_the_post_thumbnail_url($post->ID, 'full');
            
        if ( isset( $schema['properties']['product_data_brand'] ) )
            $post_data['product_data_brand'] = carbon_get_post_meta($post->ID,'product_data_brand');

        if ( isset( $schema['properties']['product_data_model'] ) )
            $post_data['product_data_model'] = carbon_get_post_meta($post->ID,'product_data_model');

        if ( isset( $schema['properties']['product_data_size'] ) )
            $post_data['product_data_size'] = carbon_get_post_meta($post->ID,'product_data_size');

        if ( isset( $schema['properties']['product_data_type'] ) )
            $post_data['product_data_type'] = carbon_get_post_meta($post->ID,'product_data_type');

        if ( isset( $schema['properties']['product_data_tread'] ) )
            $post_data['product_data_tread'] = carbon_get_post_meta($post->ID,'product_data_tread');

        if ( isset( $schema['properties']['product_data_price'] ) )
            $post_data['product_data_price'] = carbon_get_post_meta($post->ID,'product_data_price');

        if ( isset( $schema['properties']['product_data_images'] ) )
            $post_data['product_data_images'] = carbon_get_post_meta($post->ID,'product_data_images');

        if ( isset( $schema['properties']['product_data_desc'] ) )
            $post_data['product_data_desc'] = carbon_get_post_meta($post->ID,'product_data_desc');

        if ( isset( $schema['properties']['category'] ) )
            $post_data['categories'] = wp_get_post_terms($post->ID, 'category_of_product', array('fields' => 'ids'));

        return $post_data;
    }

    /**
     * Подготавливает ответ отдельного ресурса для добавления его в коллекцию ресурсов.
     *
     * @param WP_REST_Response $response Response object.
     *                                   
     * @return array|mixed Response data, ready for insertion into collection data.
     */
    function prepare_response_for_collection( $response ){

        if ( ! ( $response instanceof WP_REST_Response ) ){
            return $response;
        }

        $data = (array) $response->get_data();
        
        $server = rest_get_server();

        if ( method_exists( $server, 'get_compact_response_links' ) ){
            $links = call_user_func( [ $server, 'get_compact_response_links' ], $response );
        }
        else {
            $links = call_user_func( [ $server, 'get_response_links' ], $response );
        }

        if ( ! empty( $links ) ){
            $data['_links'] = $links;
        }

        return $data;
    }

    ## Схема ресурса.
    function get_item_schema(){
        $schema = [
            // показывает какую версию схемы мы используем - это draft 4
            '$schema'    => 'http://json-schema.org/draft-04/schema#',
            // определяет ресурс который описывает схема
            'title'      => 'product',
            'type'       => 'object',
            // в JSON схеме нужно указывать свойства в атрибуете 'properties'.
            'properties' => [
                'id' => [
                    'type'        => 'integer',
                ],
                'title' => [
                    'type'        => 'string',
                ],
                'product_data_brand' => [
                    'type'        => 'string',
                ],
                'featured_image' => [
                    'type'        => 'string',
                ],
                'product_data_model' => [
                    'type'        => 'string',
                ],
                'product_data_size' => [
                    'type'        => 'string',
                ],
                'product_data_type' => [
                    'type'        => 'string',
                ],
                'product_data_tread' => [
                    'type'        => 'string',
                ],
                'product_data_price' => [
                    'type'        => 'string',
                ],
                'product_data_images' => [
                    'type'        => 'array',
                ],
                'product_data_desc' => [
                    'type'        => 'string',
                ],
                'category' => [
                    'type'        => 'array',
                ],
                // TODO добавить поля
                // []
            ],
        ];

        return $schema;
    }

}
?>

Upvotes: 0

Views: 2049

Answers (2)

MuturiAlex
MuturiAlex

Reputation: 358

    $posts= new WP_Query(array(
            'post_per_page' => 3,
            'orderby'     => 'date',
            'order'       => 'DESC',
            'post_type'   => 'products',
        ));

    // Create the response object
    $response = new WP_REST_Response( $data );
    
    // set header for X-WP-Total and X-WP-TotalPages
    $max_pages = $posts->max_num_pages;
    $total_posts = $posts->found_posts;
    $response->header( 'X-WP-Total', $total_posts );   
    $response->header( 'X-WP-TotalPages', $max_pages);

    // Add a custom status code
    $response->set_status( 200 );
    return $response;

Upvotes: 1

plaglamist
plaglamist

Reputation: 53

Here is my solution. now i have in that Rest Api headers that i needed and it does search too ^_^

<?php
/**
 * Plugin Name: Custom API Plugin
 * Description: That plugin creates some custom end points for wp-admin
 * Author: Ahma
 * Version: 1
 */

add_action( 'rest_api_init', 'prefix_register_my_rest_routes' );
function prefix_register_my_rest_routes() {
    $controller = new My_REST_Posts_Controller();
    $controller->register_routes();
}

class My_REST_Posts_Controller extends WP_REST_Controller {

    function __construct(){
        $this->namespace = 'wl/v1';
        $this->rest_base = 'products';
    }

    function register_routes(){

        register_rest_route( $this->namespace, "/$this->rest_base", [
            [
                'methods'             => 'GET',
                'callback'            => [ $this, 'get_items' ],
            ],
            'schema' => [ $this, 'get_item_schema' ],
        ] );

        register_rest_route( $this->namespace, "/$this->rest_base/(?P<id>[\w]+)", [
            [
                'methods'   => 'GET',
                'callback'  => [ $this, 'get_item' ],
            ],
            'schema' => [ $this, 'get_item_schema' ],
        ] );
    }


    /**
     * Получает последние посты и отдает их в виде rest ответа.
     *
     * @param WP_REST_Request $request Текущий запрос.
     *
     * @return WP_Error|array
     */
    function get_items($request ){
        $data = [];
        
        $page = isset($request->get_params()['page'])? $request->get_params()['page']: 1;
        
        $search_query = isset($request->get_params()['sq'])? $request->get_params()['sq']: null;
        
        $posts =  new WP_Query(array(
          'posts_per_page' => 10,
          'orderby'     => 'date',
          'order'       => 'DESC',
          'post_type'   => 'products',
          'paged'       =>  $page,
          's'           =>   $search_query
         ));
        

     
 
        if ( empty( $posts ) )
            return $data;
        
        foreach( $posts->posts as $post ){
              $response = $this->prepare_item_for_response( $post, $request );
              $data[] = $this->prepare_response_for_collection( $response );
        }
        $max_pages = $posts->max_num_pages;
        $total_posts = $posts->found_posts;
        $data = new WP_REST_Response( $data, 200 );   
        $data->header( 'X-WP-Total', $total_posts );   
        $data->header( 'X-WP-TotalPages', $max_pages);
         
        return $data;
    }

    /**
     * Получает отдельный ресурс.
     *
     * @param WP_REST_Request $request Текущий запрос.
     *
     * @return array
     */
    function get_item( $request ){
        $id = (int) $request['id'];
        $post = get_post( $id );

        if( ! $post )
            return array();

        return $this->prepare_item_for_response( $post, $request );
    }

    /**
     * Собирает данные ресурса в соответствии со схемой ресурса.
     *
     * @param WP_Post         $post    Объект ресурса, из которого будут взяты оригинальные данные.
     * @param WP_REST_Request $request Текущий запрос.
     *
     * @return array
     */
    function prepare_item_for_response( $post, $request ){
        $post_data = [];

        $schema = $this->get_item_schema();

        // We are also renaming the fields to more understandable names.
        if ( isset( $schema['properties']['id'] ) )
            $post_data['id'] = (int) $post->ID;

        if ( isset( $schema['properties']['title'] ) )
            $post_data['title'] = apply_filters( 'the_title', $post->post_title, $post );

        if ( isset( $schema['properties']['content'] ) )
            $post_data['content'] = apply_filters( 'the_content', $post->post_content, $post );

        if ( isset( $schema['properties']['featured_image'] ) )
            $post_data['featured_image'] = get_the_post_thumbnail_url($post->ID, 'full');
            
        if ( isset( $schema['properties']['product_data_brand'] ) )
            $post_data['product_data_brand'] = carbon_get_post_meta($post->ID,'product_data_brand');

        if ( isset( $schema['properties']['product_data_model'] ) )
            $post_data['product_data_model'] = carbon_get_post_meta($post->ID,'product_data_model');

        if ( isset( $schema['properties']['product_data_size'] ) )
            $post_data['product_data_size'] = carbon_get_post_meta($post->ID,'product_data_size');

        if ( isset( $schema['properties']['product_data_type'] ) )
            $post_data['product_data_type'] = carbon_get_post_meta($post->ID,'product_data_type');

        if ( isset( $schema['properties']['product_data_tread'] ) )
            $post_data['product_data_tread'] = carbon_get_post_meta($post->ID,'product_data_tread');

        if ( isset( $schema['properties']['product_data_price'] ) )
            $post_data['product_data_price'] = carbon_get_post_meta($post->ID,'product_data_price');

        if ( isset( $schema['properties']['product_data_images'] ) )
            $post_data['product_data_images'] = carbon_get_post_meta($post->ID,'product_data_images');

        if ( isset( $schema['properties']['product_data_desc'] ) )
            $post_data['product_data_desc'] = carbon_get_post_meta($post->ID,'product_data_desc');

        if ( isset( $schema['properties']['category'] ) )
            $post_data['categories'] = wp_get_post_terms($post->ID, 'category_of_product', array('fields' => 'ids'));

        return $post_data;
    }

    /**
     * Подготавливает ответ отдельного ресурса для добавления его в коллекцию ресурсов.
     *
     * @param WP_REST_Response $response Response object.
     *                                   
     * @return array|mixed Response data, ready for insertion into collection data.
     */
    function prepare_response_for_collection( $response ){

        if ( ! ( $response instanceof WP_REST_Response ) ){
            return $response;
        }

        $data = (array) $response->get_data();
        $server = rest_get_server();

        if ( method_exists( $server, 'get_compact_response_links' ) ){
            $links = call_user_func( [ $server, 'get_compact_response_links' ], $response );
        }
        else {
            $links = call_user_func( [ $server, 'get_response_links' ], $response );
        }

        if ( ! empty( $links ) ){
            $data['_links'] = $links;
        }

        return $data;
    }

    ## Схема ресурса.
    function get_item_schema(){
        $schema = [
            // показывает какую версию схемы мы используем - это draft 4
            '$schema'    => 'http://json-schema.org/draft-04/schema#',
            // определяет ресурс который описывает схема
            'title'      => 'product',
            'type'       => 'object',
            // в JSON схеме нужно указывать свойства в атрибуете 'properties'.
            'properties' => [
                'id' => [
                    'type'        => 'integer',
                ],
                'title' => [
                    'type'        => 'string',
                ],
                'product_data_brand' => [
                    'type'        => 'string',
                ],
                'featured_image' => [
                    'type'        => 'string',
                ],
                'product_data_model' => [
                    'type'        => 'string',
                ],
                'product_data_size' => [
                    'type'        => 'string',
                ],
                'product_data_type' => [
                    'type'        => 'string',
                ],
                'product_data_tread' => [
                    'type'        => 'string',
                ],
                'product_data_price' => [
                    'type'        => 'string',
                ],
                'product_data_images' => [
                    'type'        => 'array',
                ],
                'product_data_desc' => [
                    'type'        => 'string',
                ],
                'category' => [
                    'type'        => 'array',
                ],
                // TODO добавить поля
                // []
            ],
        ];

        return $schema;
    }

}
?>

Upvotes: 2

Related Questions