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://developer.wordpress.org/reference/functions/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,否则它将默认为文章类型的名称。在下例中,“books”被用作 rest_base 的值。这将使路由的 URL 变为 wp-json/wp/v2/books,而不是默认为 wp-json/wp/v2/book/。

此外,您可以传递 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://developer.wordpress.org/reference/functions/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_controller_class,则 REST API 无法自动确定给定文章的路线。在这种情况下,您可以使用 rest_route_for_post 过滤器来提供此信息。这允许您的自定义文章类型在搜索端点中正确格式化,并启用自动发现链接。

function my_plugin_rest_route_for_post( $route, $post ) {
    if ( $post->post_type === 'book' ) {
        $route = '/wp/v2/books/' . $post->ID;
    }

    return $route;
}
add_filter( 'rest_route_for_post', 'my_plugin_rest_route_for_post', 10, 2 );

注册支持 REST API 的自定义分类法

注册支持 REST API 的自定义分类法与注册自定义文章类型非常相似:在传递给 register_taxonomy 的参数中传递 'show_in_rest' => true。您可以选择传递 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://developer.wordpress.org/reference/functions/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_controller_class,则 REST API 无法自动确定给定术语的路线。在这种情况下,您可以使用 rest_route_for_term 过滤器来提供此信息。这允许您的自定义分类法在搜索端点中正确格式化,并启用自动发现链接。

function my_plugin_rest_route_for_term( $route, $term ) {
    if ( $term->taxonomy === 'genre' ) {
        $route = '/wp/v2/genre/' . $term->term_id;
    }

    return $route;
}
add_filter( 'rest_route_for_term', 'my_plugin_rest_route_for_term', 10, 2 );

向现有内容类型添加 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 内部具有内置关联,但如果您想在两个自定义文章类型之间建立链接呢?WordPress 本身并未正式支持这一点,但我们可以使用 _link 关系在任意内容类型之间创建我们自己的连接。