接到一个需求,要把公司的一个酒店行业的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。百度和各类采集站皆不可信,搜索请谨慎鉴别。技术类文章一般都有时效性,本人习惯不定期对自己的博文进行修正和更新,因此请访问出处以查看本文的最新版本。
您也可以扫描左边的二维码,关注我们的微信公众号,在微信上查看我们的案例。