WordPress Rest API 学习笔记(一)

接到一个需求,要把公司的一个酒店行业的WordPress网站里的几百家酒店数据导出为CSV文件,以便其他开发人员把它转成需要的格式开发APP。觉得这是一个比较笨的需求,WP是一套十分便捷的CMS,用WP后台管理这些酒店数据很容易,但对方是要拿静态的CSV文件,转格式后,就要导入另一套不如WP好用的后台。同一套数据两边分别管理,实在是浪费人力。我们为什么不能直接通过WordPress后台同时管理网站和APP数据呢?

由这个切入点,让我想起了WP REST API,从最近发布的WP的4.7版开始,已经官方支持REST API,不需要安装任何插件了。这也是现在的技术趋势,使得WordPress不再局限于PHP语言,能够导出JSON数据被任何其他开发语言和平台所使用。

REST API的基本概念就是直接把网站数据通过类似
http://yourdomain.com/wp-json/wp/v2/posts/
http://yourdomain.com/wp-json/wp/v2/pages/
这样的URL转成JSON
这个URL可以再定义得细一些,比如
…/wp-json/wp/v2/posts/53
就是输出ID为53的文章
再比如
…/wp-json/wp/v2/posts?categories=5
获得分类ID为5的文章

显然这里我用的是Rest API 2,所以URL里面都带V2

再举几个例子
获得分类ID为4和5的文章:…/wp-json/wp/v2/posts?categories=4+5
获得分类为5的数据:…/wp-json/wp/v2/categories/5
默认只显示10条数据,我们可以定义多一点(最多100),并且让它根据标题排序: …/wp-json/wp/v2/posts?per_page=100&orderby=title&order=asc

有点意思啊!
更多怎么玩URL的案例,可以去REST API官方文档查看: http://v2.wp-api.org

以上只有WP默认的文章类型提供了现成的URL可调用,我们开发网站往往要用到很多自定义文章类型(Custom Post Type),简称CPT,很熟悉的名字吧?
出于安全起见,CPT是没有直接调用的,需要写代码开放接口。

比如这次我们把酒店都写成一个CPT,名叫hotel
在注册这个CPT的时候用到再熟悉不过的register_post_type
这时候只要加上一个参数 ‘show_in_rest’ => true 就可以开放hotel的查询了
具体代码是这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
add_action('init', 'create_hotel_post_type', 0);
function create_hotel_post_type() {
	register_post_type('hotel', array(
		'label' => 'Hotels',
		'description' => '',
		'public' => true,
		'show_ui' => true,
		'show_in_menu' => true,
		'show_in_rest' => true, //使这个CPT支持REST API
		'capability_type' => 'post',
		'hierarchical' => false,
		'rewrite' => array('slug' => ''),
		'query_var' => true,
		'supports' => array('title','editor',),
		'labels' => array (
			'name' => 'All hotels',
			....//此处省略
		)
	);
}

这样,我们就能很方便的用 …/wp-json/wp/v2/hotel/ 加上参数直接查询数据了

如果你的CPT是通过插件加上的,也可以这么写:

1
2
3
4
5
6
7
8
9
10
add_action( 'init', 'my_custom_post_type_rest_support', 25 );
function my_custom_post_type_rest_support() {
  	global $wp_post_types;
  	$post_type_name = 'hotel';
  	if( isset( $wp_post_types[ $post_type_name ] ) ) {
  		$wp_post_types[$post_type_name]->show_in_rest = true;
  		$wp_post_types[$post_type_name]->rest_base = $post_type_name;
  		$wp_post_types[$post_type_name]->rest_controller_class = 'WP_REST_Posts_Controller';
  	}
}

有了CPT,我们还要加上它的好兄弟CPM(Custom Post Meta),即自定义字段。因为他们是不会出现在默认的JSON数据里的。通过rest_prepare_[CPT名]这个filter就可以任意修改输出的JSON数据了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function filter_hotel_json( $data, $post, $context ) {
	//以下是要添加的自定义字段
	$data->data['hotel_address'] = esc_html( get_post_meta( $post->ID, 'hotel_address', true ) );
	$data->data['hotel_zipCode'] = esc_html( get_post_meta( $post->ID, 'hotel_zipCode', true ) );
	$data->data['hotel_city'] = esc_html( get_post_meta( $post->ID, 'hotel_city', true ) );
	$data->data['hotel_country'] = esc_html( get_post_meta( $post->ID, 'hotel_country', true ) );
	$data->data['hotel_tel'] = esc_html( get_post_meta( $post->ID, 'hotel_tel', true ) );
	$data->data['hotel_fax'] = esc_html( get_post_meta( $post->ID, 'hotel_fax', true ) );
	...
	//以下是删除某个字段
	unset( $data->data['featured_media'] );
 
	return $data;
}
add_filter( 'rest_prepare_hotel', 'filter_hotel_json', 10, 3 );

如果想要输出完全自定义格式的JSON,也可以这样

1
2
3
4
5
6
7
8
9
10
11
12
function filter_hotel_json( $data, $post, $context ) {
	return array(
		'id'		=> $data->data['id'],
		'title'    	=> $data->data['title']['rendered'],
		'link'     	=> $data->data['link'],
		'hotel_address' => esc_html( get_post_meta( $post->ID, 'hotel_address', true ) ),
		'hotel_zipCode' => esc_html( get_post_meta( $post->ID, 'hotel_zipCode', true ) );
		'hotel_city'    => esc_html( get_post_meta( $post->ID, 'hotel_city', true ) );
		...
	);
}
add_filter( 'rest_prepare_hotel', 'filter_hotel_json', 10, 3 );

对于自定义分类,也需要在注册分类的时候加上参数 ‘show_in_rest’ => true

1
2
3
4
5
6
7
8
9
10
11
12
13
register_taxonomy(
		'hotel_category',
		'hotel',
		array(
			'labels' => array(
				...
			),
			'show_ui' => true,
			'show_tagcloud' => false,
			'hierarchical' => true,
			'show_in_rest' => true //使这个分类支持REST API
		)
	);

自定义分类hotel_category的分类列表: …/wp-json/wp/v2/hotel_category/
分类为12的自定义类型文章列表:…/wp-json/wp/v2/hotel?hotel_category=12

或者这样写

1
2
3
4
5
function add_custom_tax_to_api() {
    $mytax = get_taxonomy( 'hotel_category' );
    $mytax->show_in_rest = true;
}
add_action( 'init', 'add_custom_tax_to_api', 30 );

一次加上所有的自定义分类支持:

1
2
3
4
5
6
7
8
function add_custom_taxes_to_api() {
    $taxonomies = get_taxonomies( '', 'objects' );
 
    foreach( $taxonomies as $taxonomy ) {
        $taxonomy->show_in_rest = true;
    }
}
add_action( 'init', 'add_custom_taxes_to_api', 30 );

如果在自定义分类里面增加了一个分类字段,仍然可以用钩子 rest_prepare_分类名 来修改
同样以自定义类别hotel_category举例,在这个类别里我们增加了缩略图字段cat_thumbnail,可以这样增加到API中:

1
2
3
4
5
6
function filter_hotel_category_json( $data, $term, $request ) {
	$cat_thumbnail = get_terms_meta($term->term_id, "cat_thumbnail");
	$data->data['theme_thumbnail'] = $cat_thumbnail;
	return $data;
}
add_filter( 'rest_prepare_hotel_category', 'filter_hotel_category_json', 10, 3 );

本站所有文章均为原创,欢迎转载,请注明文章出处:https://blog.brain1981.com/1511.html。百度和各类采集站皆不可信,搜索请谨慎鉴别。技术类文章一般都有时效性,本人习惯不定期对自己的博文进行修正和更新,因此请访问出处以查看本文的最新版本。

如本文对你有用,请在页面右侧栏扫码领取我的支付宝红包,作为打赏吧 (喂到底是我赏你还是你赏我啊-_-!)

关注我们的微信公众号-JennyStudio 本站记录了近几年的工作中遇到的一些技术问题和解决过程,“作品集”还收录了本人的大部分作品展示。除了本博客外,我们的工作室网站 – JennyStudio,内有更多作品回顾和展示。
您也可以扫描左边的二维码,关注我们的微信公众号,在微信上查看我们的案例。

发表评论

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