wp-rest-api-modify-response

WP REST API响应体(Response)个性化定制

在《WP Rest API 入门详解》中,我们已经介绍了WP REST API的基础知识和常用的API接口用法。同时也提到,在实际的开发中,使用WP REST API 内置默认的API接口并不高效合理。需要根据实现开发需求作定制。

本文就谈谈WP REST API 响应体(Response)的个性化定制。

一、需求及分析

首先,先看看上篇文章给出的单篇文章默认的响应信息内容,如下图。

post

假如我们现在做一个以wordpress为后台的前端客户端程序,我们在前端通过AJAX调用wordpress的文章数据。功能需要主要是两部分:一部分是显示一个文章列表,另一部分是当用户点击某篇文章后,查看文章的详情。

我们现在根据这个需求来做下简单的分析:

1、需求方面。文章列表页面需要文章ID、标题(title)、日期(date)、缩略图(假如有)这些数据。文章详情页面需要文章ID、标题(title)、日期(date)、特色图像(假如有)、内容(content)、分类(categories)和标签(tags)。

2、性能优化。因为我们是以wordpress为后台(backend),以AJAX请求调用数据,因此,请求连接数和响应体(Response)的数量和“体量”将会影响整体性能。

通过以上分析后,我们现在可以明确对WP REST API默认响应体(Response)的定制要求。

首先,在请求获取文章列表(GET posts)时,我们需要文章有一个缩略图字段,在默认的响应体(Response)里,没有直接的缩略图字段,只有特色图像的媒体ID字段,因此,我们增加一个特色图像的缩略图字段,并且字段最好就是直接的缩略图URL地址,不需要再做获取特色图像的请求,减少请求数,我们把这个特色图像缩略图字段设为:thumbnailurl。同时,我们要把多余的字段全部过滤掉。只返回文章ID、标题(title)、日期(date)、缩略图(假如有)这些字段的数据。

同样的理由,在文章详情中,我们需要把特色图像URL地址、分类、标签的字段加进去,同样过滤掉其他多余的字段。
OK. 接下来就开始来实现。

 

二、修改WP REST API响应体(Modifying Responses)

首先,我们先明确对WP REST API响应体(Response)的修改是两个方面,一是增加字段,二是过滤字段。所以我们可以通过wordpress中add_filter过滤rest_prepare_post来实现。

1、文章中加入缩略图

/* 文章中加入缩略图 */
add_filter( 'rest_prepare_post', 'my_rest_prepare_post', 10, 3 );

function my_rest_prepare_post( $data, $post, $request ) {
   $_data = $data->data;
   $thumbnail_id = get_post_thumbnail_id( $post->ID );
   $thumbnail = wp_get_attachment_image_src( $thumbnail_id );
   $_data['thumbnailurl'] = $thumbnail[0];
   $data->data = $_data;
   return $data;
}

以上代码中,通过add_filter来添加响应过滤。在响应函数my_rest_prepare_post中,$request表示发起的请求,$data表示全部数据,$post表示单个数据。

加入上面的代码后,就可以在响应中得到一个thumbnailurl字段,指向缩略图的URL地址。

以上代码存在着一些问题,比如特色图像也可能没有,所以我们对这个函数再优化一下。

function my_rest_prepare_post( $data, $post, $request ) {
    $_data = $data->data;
if ( has_post_thumbnail() ) {
    $thumbnail_id = get_post_thumbnail_id( $_data['id'] );
    $thumbnail = wp_get_attachment_image_src( $thumbnail_id , 'thumbnail' );
    $thumbnailurl = $thumbnail[0];
    $featuredimgurl = $featuredimg[0];
    if( ! empty($thumbnailurl)){
        $_data['thumbnailurl'] = $thumbnailurl;
    }
    }else{
        $_data['thumbnailurl'] = null;
    }
    $data->data = $_data;
    return $data;
}

2、过滤数据

我们在my_rest_prepare_post函数中,构造一个新的数组来指定所包含的字段,并把这个数组作为响应体(Response)返回。

function my_rest_prepare_post( $data, $post, $request ) {
$_data = $data->data;
if ( has_post_thumbnail() ) {
$thumbnail_id = get_post_thumbnail_id( $_data['id'] );
$thumbnail = wp_get_attachment_image_src( $thumbnail_id , 'thumbnail' );
$thumbnailurl = $thumbnail[0];
$featuredimgurl = $featuredimg[0];
if( ! empty($thumbnailurl)){
$_data['thumbnailurl'] = $thumbnailurl;
}
}else{
$_data['thumbnailurl'] = null;
}
$data->data = $_data;
$pure_post = array();
$pure_post['id'] = $_data['id'];
$pure_post['title'] = $_data['title']['rendered'];
$pure_post['date'] = $_data['date'];
$pure_post['thumbnailurl'] = $_data['thumbnailurl'];
return $pure_post;
}

我们可以看到,这时就是纯粹我们需要的文章列表的数据了。

pure_post

3、详情页

当我们做完上面一步,我们在请求单篇文章时,发现问题来了,单篇文章(也即是文章详情)返回的数据也只有id,title,date和thumbnailurl四个字段。所有的字段都在上一步被过滤掉了。

pure_post2

因此,我们在做过滤的时候,要多一个判断的步骤,判断请求的是列表页还是详情页。如果是列表页就返回以上四个字段,如果是详情页,就还要增加分类、标签、文章内容、特色图像等字段。

PS: 本人在此处就踩过坑,幸得台湾一位大神Yoren Chang的帮忙,在此深表谢意。这是Yoren Chang的网站(https://1fix.io/),内容都是干货,赞一个。

值得注意的是,我们无法直接获取分类和标签,因此,此处要另外构造一个函数,专门用来获取分类和标签数据。

最后,完整的代码如下:

add_filter( 'rest_prepare_post', 'my_rest_prepare_post', 10, 3 );

function my_rest_prepare_post( $data, $post, $request ) {
    $_data = $data->data;

    if ( has_post_thumbnail() ) {
        $thumbnail_id = get_post_thumbnail_id( $_data['id'] );
        $thumbnail = wp_get_attachment_image_src( $thumbnail_id , 'thumbnail' );
        $featuredimg = wp_get_attachment_image_src( $thumbnail_id , 'full' );
        $thumbnailurl = $thumbnail[0];
        $featuredimgurl = $featuredimg[0];
        if( ! empty($thumbnailurl)){
            $_data['thumbnailurl'] = $thumbnailurl;
        }
        if( ! empty($featuredimgurl)){
            $_data['featuredimgurl'] = $featuredimgurl;
        }
    }else{
        $_data['thumbnailurl'] = null;
        $_data['featuredimgurl'] = null;
    }

    $pure_post = array();
    $pure_post['id'] = $_data['id'];
    $pure_post['title'] = $_data['title']['rendered'];
    $pure_post['date'] = $_data['date'];
    $pure_post['thumbnailurl'] = $_data['thumbnailurl'];

    $params = $request->get_params();
    if ( isset( $params['id'] ) ) {

        $categories = my_rest_get_post_terms( $_data['id'], 'category' );
        if ( ! empty( $categories ) ) {
            $_data['categories'] = $categories;
        }

        $tags = my_rest_get_post_terms( $_data['id'], 'post_tag' );
        if ( ! empty( $tags ) ) {
            $_data['tags'] = $tags;
        }

    $pure_post['categories'] = $_data['categories'];
    $pure_post['tags'] = $_data['tags'];
    $pure_post['featuredimgurl'] = $_data['featuredimgurl'];
    $pure_post['content'] = $_data['content']['rendered'];

    }

    return $pure_post;

}

function my_rest_get_post_terms( $id = false, $taxonomy = 'category' ) {
    if ( ! $id ) {
        return FALSE;
    }
    $valid_tax = apply_filters( 'my_rest_valid_tax', array( 'category', 'post_tag' ) );
    $taxonomy = ( in_array( $taxonomy, $valid_tax ) ) ? $taxonomy : 'category';
    $terms = wp_get_post_terms( absint( $id ), $taxonomy );
    if ( ! is_wp_error( $terms ) && ! empty( $terms ) ) {
        foreach ( $terms as $term ) {
            $link = get_term_link( $term );
            $term->link = $link;
        }
    }
    return $terms;
}

4、整合打包

我们可以把这个需求实现打包成一个插件,要使用时直接安装启用插件即可。

我已把插件放到我的Github上面,大家如果有需要,可以直接下载安装使用。

插件Github地址:https://github.com/yaoyonstudio/rest-api-modify-response

最后,通过以上讲解,如果想获取或过滤其他的字段,都可以自定义,非常方便。

 

四、关于WP REST API的register_rest_field

在 WP REST API 官网中,Modifying Responses 一章介绍了修改响应体(Response)的方法。

WP REST API 提供了register_rest_field函数来注册和修改响应体中的字段。关于register_rest_field函数,官网这样描述:

register_rest_field provides a single way for modifying all responses for an object. For example, if it is used to add a field to the posts object, this field will be included in all responses, whether they are for single or multiple items.

此方法用于注册增加字段,如果你的wordpress中有自定义的文章类型,或是自定义的字段,可以register_rest_field来注册增加。

 

好了,本文关于WP REST API 响应体(Response)的个性化定制就暂时讲到这里。

 

那时那我

jinyunblogadmin

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据