Wordpress REST API の出力結果を整形して絞り込む方法

#やりたいこと
- カスタムフィールドをAPI出力したい。
- パラメータを渡して任意のカスタムフィールドを検索の対象に含めて結果を出力したい。
- ラジオボタンのカスタムフィールド はOR検索にしたい。
- 期限切れのものは除外したい。


#前提条件
- WordPress 4.9.3
- カスタムフィールド は「Smart Custom Fields」を使用。


#カスタムフィールドをapi出力する

##カスタム投稿タイプを登録

**function.php**

```function.php
function create_post_type() {
  $supports = [ 
    'title',  // title
    'editor',  // editor
  ];
  register_post_type( 'coupon',  //  クーポン
    array(
      'label' => 'クーポン',  
      'public' => true,  
      'has_archive' => false,  
      'menu_position' => 7, 
      'supports' => $supports, 
      'show_in_rest' => true, //rest api での取得有効にする
      'rest_base' => 'coupon' // rest api での取得名  /wp-json/wp/v2/coupon
    )
  );
}
add_action( 'init', 'create_post_type' );
```

##カスタムフィールドを登録

「Smart Custom Fields」でカスタムフィールド を登録します。
仮に以下の３つを登録したとします。

| ラベル | タイプ | 名前 | 日付のフォーマット |ラジオボタンの選択肢 |
|:-:|:-:|:-:|:-:|:-:|
| 種類 | ラジオボタン  | coupon_type |   | ハンバーガー<br>フライドポテト  |
| エリア | テキスト |  coupon_area |   |   |
| 終了日 | 日付ピッカー  |  coupon_use_finish | yy/mm/dd  |   |

### function.phpに以下を追記
rest apiで出力できるようにします。

```function.php
add_action( 'rest_api_init', 'slug_register_onsen' );
function slug_register_onsen() {
    register_rest_field( 'coupon', //フィールドを追加したいcustom投稿タイプを指定（先ほど登録したカスタム投稿タイプslugを指定）
        'data', 
        array(
            'get_callback'  => function(  $object, $field_name, $request  ) {
              // 出力したいカスタムフィールドのキーをここで定義
              $meta_fields = array(
                'coupon_type',
                'coupon_area',
                'coupon_use_finish',
              );
              $meta = array();
              foreach ( $meta_fields as $field ) {
                $meta[ $field ] = get_post_meta( $object[ 'id' ], $field, true );
              }
              return $meta;
            },
            'update_callback' => null,
            'schema'          => null,
        )
    );
}
```

###適当に記事を登録する

###ここまでの出力結果

http://example/wp-json/wp/v2/coupon/
カスタムフィールドの値が出力されています。

```js
[
  {

  ~中略~

    status: "publish",
    type: "coupon",
    link: "http://example/coupon/xxxxxx/",
    title: {
      rendered: "クーポン1"
    },
    content: {
      rendered: "",
      protected: false
    },
    template: "",
    data: {
      coupon_type: "ハンバーガー",
      coupon_area: "関東",
      coupon_display_finish: "2018/02/17",
    },

  ~中略~

  }
]
```

#【本題】パラメータを渡してカスタムフィールドを検索の対象に含めて結果を出力

検索結果はカスタムURLにする。
こんな感じでパラメータを渡す想定。
http://example/wp-json/search/coupon/?type[]=ハンバーガー&type[]=フライドポテト&area=関東

- ラジオボタンのカスタムフィールド はOR検索にする
- 期限切れのものは出力結果から除外
- パラメータを渡せば期限切れのものも出力するように

**function.php**

```function.php
function search_coupon(){

  global $post;
  $param = $_GET;
  $args = array( 
    'post_type'  => 'coupon',// カスタム投稿名「coupon」
    'meta_query' => array(
      // 'relation' => 'OR',
    ),
  );
  $data = array();
  $time = array();


  //クーポン種類
  if ( !empty($param['type']) ) {
    array_push( $args['meta_query'] , array(
      'key'     => 'coupon_type',
      'value'   => $param['type'],
      'compare' => 'IN',
    ));
  }


  // デフォルトは期限が切れていないをクーポンを返す。パラメータもらった時だけ全表示
  $currnet_date = date_i18n( 'y/m/d' );

  if ( empty($param['finish']) ) {
    array_push( $args['meta_query'] , array(
      'type' => 'DATE',
      'key'     => 'coupon_use_finish',
      'value'   => $currnet_date,
      'compare' => '>=',
    ));
  }


  $posts2 = get_posts( $args );

  // 出力形式を整形
  foreach ( $posts2 as $post ) {
    $data[] = array(
      'title'     => get_the_title(),
      'coupon_type' => post_custom( 'coupon_type' ),
      'coupon_area' => post_custom( 'coupon_area' ),
      'coupon_use_finish' => post_custom( 'coupon_use_finish' ),
    );
  }

  $response = new WP_REST_Response($data);
  return $response;

}


add_action( 'rest_api_init', function () {
  register_rest_route( 'search/', 'coupon/', array(
    'methods' => 'GET',
    'callback' => 'search_coupon',
  ));
});
```

###出力結果 (検索日が「2018/02/10」の場合)

**期限切れ含めて全て表示**
http://example/wp-json/search/coupon/?finish=1

```js
[
  {
    title: "クーポン１",
    coupon_type: "ハンバーガー",
    coupon_area: "関東",
    coupon_display_finish: "2018/02/17",
  },
  {
    title: "クーポン2",
    coupon_type: "フライドポテト",
    coupon_area: "関東",
    coupon_display_finish: "2018/01/10",
  },
  {
    title: "クーポン3",
    coupon_type: "ハンバーガー",
    coupon_area: "九州",
    coupon_display_finish: "2018/03/17",
  },
  {
    title: "クーポン4",
    coupon_type: "フライドポテト",
    coupon_area: "九州",
    coupon_display_finish: "2018/03/17",
  }
]
```

**coupon_typeがハンバーガーのクーポンを検索**
http://example/wp-json/search/coupon/?type[]=ハンバーガー

```js
[
  {
    title: "クーポン１",
    coupon_type: "ハンバーガー",
    coupon_area: "関東",
    coupon_display_finish: "2018/02/17",
  },
  {
    title: "クーポン3",
    coupon_type: "ハンバーガー",
    coupon_area: "九州",
    coupon_display_finish: "2018/03/17",
  }
]
```


**coupon_typeがハンバーガー、or フライドポテトのクーポンを検索**
http://example/wp-json/search/coupon/?type[]=ハンバーガー&type[]=フライドポテト
期限切れのクーポンは出力されない

```js
[
  {
    title: "クーポン１",
    coupon_type: "ハンバーガー",
    coupon_area: "関東",
    coupon_display_finish: "2018/02/17",
  },
  {
    title: "クーポン3",
    coupon_type: "ハンバーガー",
    coupon_area: "九州",
    coupon_display_finish: "2018/03/17",
  },
  {
    title: "クーポン4",
    coupon_type: "フライドポテト",
    coupon_area: "九州",
    coupon_display_finish: "2018/03/17",
  }
]
```


**coupon_typeがハンバーガー、or フライドポテトで関東のクーポンを検索**
http://example/wp-json/search/coupon/?type[]=ハンバーガー&type[]=フライドポテト&area=関東
期限切れのクーポンは出力されない。areaはAND検索なので九州は出力されない。

```js
[
  {
    title: "クーポン１",
    coupon_type: "ハンバーガー",
    coupon_area: "関東",
    coupon_display_finish: "2018/02/17",
  }
]
```

**coupon_typeがハンバーガー、or フライドポテトで期限切れ含めた関東のクーポンを検索**
http://example/wp-json/search/coupon/?type[]=ハンバーガー&type[]=フライドポテト&area=関東&finish=1
期限切れのクーポンは出力される。areaはAND検索なので九州は出力されない。

```js
[
  {
    title: "クーポン１",
    coupon_type: "ハンバーガー",
    coupon_area: "関東",
    coupon_display_finish: "2018/02/17",
  },
  {
    title: "クーポン2",
    coupon_type: "フライドポテト",
    coupon_area: "関東",
    coupon_display_finish: "2018/01/10",
  },
]
```