カスタム投稿タイプ、カスタムタクソノミーをREST APIで利用する

2020.03.25 2020.03.25

TOPICS

REST API は、デフォルトの投稿タイプやタクソノミータームのコントローラと同じコントローラを使用して、 wp/v2 ネームスペース内にカスタム投稿タイプやカスタムタクソノミーのルートを作成することができます。
あるいは、独自のコントローラとネームスペースを使用することもできます。このドキュメントでは、カスタムコンテンツタイプの API ルートにデフォルトのコントローラを使用する方法を説明します。
これは最も簡単な方法であり、サードパーティとの互換性を最大限に確保することができます。

REST API対応のカスタム投稿タイプを登録する

カスタム投稿タイプを登録する際に、REST API で利用できるようにしたい場合は、 register_post_type に渡す引数に 'show_in_rest' => true を設定する必要があります。この引数を true に設定すると、wp/v2 名前空間にルートが追加されます。

/**
 * Register a book post type, with REST API support
 *
 * Based on example at: https://codex.wordpress.org/Function_Reference/register_post_type
 */
add_action( 'init', 'my_book_cpt' );
function my_book_cpt() {
    $args = array(
      'public'       => true,
      'show_in_rest' => true,
      'label'        => 'Books'
    );
    register_post_type( 'book', $args );
}

オプションで rest_base 引数を設定することで、ベースとなる URL を変更することができます。以下の例では、rest_baseの値として “books “を使用しています。これにより、ルートのURLはデフォルトの wp-json/wp/v2/book/ではなく、wp-json/wp/v2/books になります。

また、rest_controller_classにも引数を渡すことができます。このクラスは、WP_REST_Controllerのサブクラスである必要があります。デフォルトでは、WP_REST_Posts_Controllerがコントローラとして使用されています。カスタムコントローラを使用している場合は、おそらく wp/v2 の名前空間内にはないでしょう。

ここでは、完全なラベル、REST API のサポート、カスタマイズされた rest_base、デフォルトコントローラの明示的なレジストリを持つ投稿タイプを登録する例を示します。

/**
 * Register a book post type, with REST API support
 *
 * Based on example at: https://codex.wordpress.org/Function_Reference/register_post_type
 */
add_action( 'init', 'my_book_cpt' );
function my_book_cpt() {
  $labels = array(
    'name'               => _x( 'Books', 'post type general name', 'your-plugin-textdomain' ),
    'singular_name'      => _x( 'Book', 'post type singular name', 'your-plugin-textdomain' ),
    'menu_name'          => _x( 'Books', 'admin menu', 'your-plugin-textdomain' ),
    'name_admin_bar'     => _x( 'Book', 'add new on admin bar', 'your-plugin-textdomain' ),
    'add_new'            => _x( 'Add New', 'book', 'your-plugin-textdomain' ),
    'add_new_item'       => __( 'Add New Book', 'your-plugin-textdomain' ),
    'new_item'           => __( 'New Book', 'your-plugin-textdomain' ),
    'edit_item'          => __( 'Edit Book', 'your-plugin-textdomain' ),
    'view_item'          => __( 'View Book', 'your-plugin-textdomain' ),
    'all_items'          => __( 'All Books', 'your-plugin-textdomain' ),
    'search_items'       => __( 'Search Books', 'your-plugin-textdomain' ),
    'parent_item_colon'  => __( 'Parent Books:', 'your-plugin-textdomain' ),
    'not_found'          => __( 'No books found.', 'your-plugin-textdomain' ),
    'not_found_in_trash' => __( 'No books found in Trash.', 'your-plugin-textdomain' )
  );
 
  $args = array(
    'labels'             => $labels,
    'description'        => __( 'Description.', 'your-plugin-textdomain' ),
    'public'             => true,
    'publicly_queryable' => true,
    'show_ui'            => true,
    'show_in_menu'       => true,
    'query_var'          => true,
    'rewrite'            => array( 'slug' => 'book' ),
    'capability_type'    => 'post',
    'has_archive'        => true,
    'hierarchical'       => false,
    'menu_position'      => null,
    'show_in_rest'       => true,
    'rest_base'          => 'books',
    'rest_controller_class' => 'WP_REST_Posts_Controller',
    'supports'           => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments' )
  );
 
  register_post_type( 'book', $args );
}

REST API対応のカスタムタクソノミーを登録する

register_taxonomyに渡される引数に 'show_in_rest' => trueを渡すことで、REST APIに対応したカスタムタクソノミーを登録する方法は、カスタム投稿タイプを登録する方法と非常に似ています。
オプションでrest_baseを渡すことで、タクソノミーのルートのベースURLを変更することができます。

タクソノミー用のデフォルトのコントローラは WP_REST_Terms_Controller です。カスタムコントローラを使用する場合は、rest_controller_classでこれを変更することができます。

REST APIに対応したカスタムタクソノミーの登録方法の例です。

/**
 * Register a genre post type, with REST API support
 *
 * Based on example at: https://codex.wordpress.org/Function_Reference/register_taxonomy
 */
add_action( 'init', 'my_book_taxonomy', 30 );
function my_book_taxonomy() {
 
  $labels = array(
    'name'              => _x( 'Genres', 'taxonomy general name' ),
    'singular_name'     => _x( 'Genre', 'taxonomy singular name' ),
    'search_items'      => __( 'Search Genres' ),
    'all_items'         => __( 'All Genres' ),
    'parent_item'       => __( 'Parent Genre' ),
    'parent_item_colon' => __( 'Parent Genre:' ),
    'edit_item'         => __( 'Edit Genre' ),
    'update_item'       => __( 'Update Genre' ),
    'add_new_item'      => __( 'Add New Genre' ),
    'new_item_name'     => __( 'New Genre Name' ),
    'menu_name'         => __( 'Genre' ),
  );
 
  $args = array(
    'hierarchical'          => true,
    'labels'                => $labels,
    'show_ui'               => true,
    'show_admin_column'     => true,
    'query_var'             => true,
    'rewrite'               => array( 'slug' => 'genre' ),
    'show_in_rest'          => true,
    'rest_base'             => 'genre',
    'rest_controller_class' => 'WP_REST_Terms_Controller',
  );
 
  register_taxonomy( 'genre', array( 'book' ), $args );
 
}

既存のコンテンツタイプに REST API を対応させる

使用しているテーマやプラグインなど、自分で管理していないカスタム投稿タイプやカスタムタクソノミーに対してREST APIを対応させる必要がある場合は、WordPressバージョン4.6.0以降に存在するregister_post_type_argsフィルターフックを使用することができます。

/**
 * Add REST API support to an already registered post type.
 */
add_filter( 'register_post_type_args', 'my_post_type_args', 10, 2 );
 
function my_post_type_args( $args, $post_type ) {
 
    if ( 'book' === $post_type ) {
        $args['show_in_rest'] = true;
 
        // Optionally customize the rest_base or rest_controller_class
        $args['rest_base']             = 'books';
        $args['rest_controller_class'] = 'WP_REST_Posts_Controller';
    }
 
    return $args;
}

カスタムタクソノミーの場合はほぼ同じです。WordPressのバージョン4.4.0から存在するregister_taxonomy_argsフィルターを利用することができます。

/**
 * Add REST API support to an already registered taxonomy.
 */
add_filter( 'register_taxonomy_args', 'my_taxonomy_args', 10, 2 );
 
function my_taxonomy_args( $args, $taxonomy_name ) {
 
    if ( 'genre' === $taxonomy_name ) {
        $args['show_in_rest'] = true;
 
        // Optionally customize the rest_base or rest_controller_class
        $args['rest_base']             = 'genres';
        $args['rest_controller_class'] = 'WP_REST_Terms_Controller';
    }
 
    return $args;
}

カスタムリンクの関係

タクソノミーとカスタム投稿タイプには、WordPress 内での関連付けが組み込まれていますが、2 つのカスタム投稿タイプ間のリンクを確立したい場合はどうしたらいいでしょうか?
これは WordPress 自体では正式にはサポートされていませんが、_link 関係を使って任意のコンテンツタイプ間で独自の関連付けを行うことができます。