WordPressのREST APIを使って新たなエンドポイントを作成し出力内容を設定する
親サイトの投稿を子サイトから取得して表示したい時に、訳あってマルチサイトなどに出来ない場合にREST APIを使って対応するケースがあったのでまとめます。
標準のREST APIではtax_queryやmeta_queryなどの複雑な条件での投稿取得が難しいため、親サイト側に新たなエンドポイントを作成することで、細かな条件に対応し出力内容を自由に設定する事が出来ました。
正確に言うとfilterオプションを使えるようにする事でURL中に条件を追加する事が出来たのですが、TOPページなどで複数の投稿タイプをそれぞれ取得する場合などに通信が多くなったため表示がかなり遅くなる状態になりました。
https://github.com/wp-api/rest-filter/
https://developer.wordpress.org/rest-api/frequently-asked-questions/
filterオプションを使えるようにするのは元々推奨されていないやり方なので、適切にエンドポイントを作成する方が望ましいようです。
エンドポイントの登録
使用例
add_action('rest_api_init', function () {
register_rest_route('custom/v1', '/archive', array(
'methods' => 'GET',
'callback' => '_custom_archive_endpoint',
));
// register_rest_route('custom/v1', '/single', array(
// 'methods' => 'GET',
// 'callback' => '_custom_single_endpoint',
// ));
// register_rest_route('custom/v1', '/index', array(
// 'methods' => 'GET',
// 'callback' => '_custom_index_endpoint',
// ));
});
無名関数を使ってエンドポイントを登録します。
register_rest_route( string $route_namespace, string $route, array $args = array(), bool $override = false )
$route_namespace 、$routeは分かりやすければ何でも良いです。
それぞれアーカイブページ、シングルページ、TOPページで使いたいものとして登録しています。
‘callback’に様々な条件に対応した投稿情報などを返す関数名を記載します。
今回は絞り込み条件など一番複雑になった_custom_archive_endpointのみ説明します。
callback関数の設定
ややこしいので大まかに解説すると、
URLのパラメータが$requestに入ってくるので、それを元に投稿の取得条件$argsを設定。
取得した投稿群からそれぞれ投稿情報を$responseの中に格納したものを返す。
という内容になっています。
function _custom_archive_endpoint($request)
{
// リターン用配列
$response = array();
//WP_query条件の初期化
$args = array();
// リクエストからのパラメータを取得
$post_type = sanitize_text_field($request->get_param('post_type')) ?: 'post';
$word = sanitize_text_field($request->get_param('w')) ?: '';
$year = sanitize_text_field($request->get_param('y')) ?: '';
$paged = sanitize_text_field($request->get_param('n')) ?: 1;
// 現在のページの設定
if ($paged) {
$args['paged'] = $paged;
}
// キーワード検索の設定
if ($word) {
$args['s'] = $word;
}
// date_queryの設定
if ($year) {
$start_date = $year . '-01-01';
$end_date = $year . '-12-31';
$args['date_query'] = array(
array(
'after' => $start_date,
'before' => $end_date,
'inclusive' => true,
),
);
}
// tax_queryの設定
// 対応するタクソノミー
$target_taxonomy = array('category', 'tag', 'taxonomy1');
$tax_query = [];
foreach ($target_taxonomy as $taxonomy) {
$term_slug = sanitize_text_field($request->get_param($taxonomy));
//対応するタクソノミーのパラメータが設定されていたら
if ($term_slug) {
$tax_query[] = array(
'taxonomy' => $taxonomy,
'field' => 'slug',
'terms' => $term_slug,
);
}
}
// tax_queryが存在していたら条件追加
if (count($tax_query) > 0) {
$tax_query['relation'] = 'AND';
$args['tax_query'] = $tax_query;
}
// 各投稿形式ごとに条件を設定
$post_types_args = array(
'post' => array(
'post_type' => 'post',
'posts_per_page' => 10,
),
'post_type1' => array(
'post_type' => 'post_type1',
'posts_per_page' => 10,
'meta_query' => array( // 2つのフィールドいずれかが現在の日付よりも先
'relation' => 'OR',
array(
'key' => 'start_date',
'value' => date('Y/m/d'),
'compare' => '>=',
'type' => 'DATE',
),
array(
'key' => 'end_date',
'value' => date('Y/m/d'),
'compare' => '>=',
'type' => 'DATE',
),
),
'meta_key' => 'start_date',
'orderby' => 'meta_value',
'order' => 'ASC',
),
);
// 条件をまとめる
$args = array_merge($args, $post_types_args[$post_type]);
// 絞り込みの場合条件を上書き
if ($post_type === 'post_type1') {
$year = sanitize_text_field($request->get_param('date'));
if ($year) {
$args['meta_query'] = array(
'relation' => 'AND',
array(
'key' => 'start_date',
'value' => $year,
'compare' => 'LIKE',
),
);
$args['meta_key'] = 'start_date';
$args['order'] = 'ASC';
}
}
// 投稿情報を取得
$query = new WP_Query($args);
$posts = $query->posts;
// 投稿情報を連想配列に格納
if ($posts) {
$response['posts'] = array();
foreach ($posts as $post) {
$thumbnail = get_the_post_thumbnail($post, 'medium');
$post_data = array(
'id' => $post->ID,
'title' => $post->post_title,
'date' => $post->post_date,
'content' => $post->post_content,
'thumbnail' => $thumbnail,
// 必要に応じて他の情報も追加
);
// カテゴリー情報を取得して追加
if ($post_type == 'post') {
$terms = @get_the_terms($post, 'category');
if ($terms) {
$post_data['category'] = $terms;
}
} elseif ($post_type == 'post_type1') {
$terms = @get_the_terms($post, 'taxonomy1');
if ($terms) {
$post_data['taxonomy1'] = $terms;
}
}
// ACFのカスタムフィールドの情報をまとめて取得して追加
$custom_fields = get_fields($post->ID);
if ($custom_fields) {
$post_data['meta'] = $custom_fields;
}
$response['posts'][] = $post_data;
}
}
// ページ数などの情報を格納
$response['found_posts'] = $query->found_posts;
$response['max_num_pages'] = $query->max_num_pages;
return new WP_REST_Response($response, 200);
}