[API] Nghiên cứu về class WP_REST_Posts_Controller (ok)
Previous[API] Hướng dẫn sử dụng postman để thực hiện update bài viết (ok)Next[API][LINK] How to Get Featured Image from WordPress REST API (ok)
Last updated
Last updated
1.public function get_items
Mặc định api http://localhost/wordpress/wp-json/wp/v2/posts chỉ lấy "type": "post"
Do đó nếu muốn lấy "type": "book" chẳng hạn :)
C:\xampp\htdocs\wordpress\wp-includes\rest-api\endpoints\class-wp-rest-posts-controller.php public function get_items thay đổi thành :))
$args['post_type'] = array('post','book');
Đăng ký book ;)
C:\xampp\htdocs\wordpress\wp-content\themes\gutener\functions.php
// ===========
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',
'supports' => array('title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments'),
);
register_post_type('book', $args);
flush_rewrite_rules(true);
}
// ===========
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',
);
register_taxonomy('genre', array('book'), $args);
flush_rewrite_rules(true);
}
Và kết quả như mong đợi :)
2. get_collection_params
C:\xampp\htdocs\wordpress\wp-includes\rest-api\endpoints\class-wp-rest-controller.php
public function get_collection_params() {
return array(
'context' => $this->get_context_param(),
'page' => array(
'description' => __( 'Current page of the collection.' ),
'type' => 'integer',
'default' => 1,
'sanitize_callback' => 'absint',
'validate_callback' => 'rest_validate_request_arg',
'minimum' => 1,
),
'per_page' => array(
'description' => __( 'Maximum number of items to be returned in result set.' ),
'type' => 'integer',
'default' => 10,
'minimum' => 1,
'maximum' => 100,
'sanitize_callback' => 'absint',
'validate_callback' => 'rest_validate_request_arg',
),
'search' => array(
'description' => __( 'Limit results to those matching a string.' ),
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
'validate_callback' => 'rest_validate_request_arg',
),
);
}
public function get_context_param( $args = array() ) {
$param_details = array(
'description' => __( 'Scope under which the request is made; determines fields present in response.' ),
'type' => 'string',
'sanitize_callback' => 'sanitize_key',
'validate_callback' => 'rest_validate_request_arg',
);
$schema = $this->get_item_schema();
if ( empty( $schema['properties'] ) ) {
return array_merge( $param_details, $args );
}
$contexts = array();
foreach ( $schema['properties'] as $attributes ) {
if ( ! empty( $attributes['context'] ) ) {
$contexts = array_merge( $contexts, $attributes['context'] );
}
}
if ( ! empty( $contexts ) ) {
$param_details['enum'] = array_unique( $contexts );
rsort( $param_details['enum'] );
}
return array_merge( $param_details, $args );
}
C:\xampp\htdocs\wordpress\wp-includes\rest-api\endpoints\class-wp-rest-posts-controller.php
public function get_items( $request ) {
// Ensure a search string is set in case the orderby is set to 'relevance'.
if ( ! empty( $request['orderby'] ) && 'relevance' === $request['orderby'] && empty( $request['search'] ) ) {
return new WP_Error(
'rest_no_search_term_defined',
__( 'You need to define a search term to order by relevance.' ),
array( 'status' => 400 )
);
}
// Ensure an include parameter is set in case the orderby is set to 'include'.
if ( ! empty( $request['orderby'] ) && 'include' === $request['orderby'] && empty( $request['include'] ) ) {
return new WP_Error(
'rest_orderby_include_missing_include',
__( 'You need to define an include parameter to order by include.' ),
array( 'status' => 400 )
);
}
// Retrieve the list of registered collection query parameters.
$registered = $this->get_collection_params();
$args = array();
/*
* This array defines mappings between public API query parameters whose
* values are accepted as-passed, and their internal WP_Query parameter
* name equivalents (some are the same). Only values which are also
* present in $registered will be set.
*/
$parameter_mappings = array(
'author' => 'author__in',
'author_exclude' => 'author__not_in',
'exclude' => 'post__not_in',
'include' => 'post__in',
'menu_order' => 'menu_order',
'offset' => 'offset',
'order' => 'order',
'orderby' => 'orderby',
'page' => 'paged',
'parent' => 'post_parent__in',
'parent_exclude' => 'post_parent__not_in',
'search' => 's',
'slug' => 'post_name__in',
'status' => 'post_status',
);
/*
* For each known parameter which is both registered and present in the request,
* set the parameter's value on the query $args.
*/
foreach ( $parameter_mappings as $api_param => $wp_param ) {
if ( isset( $registered[ $api_param ], $request[ $api_param ] ) ) {
$args[ $wp_param ] = $request[ $api_param ];
}
}
echo '<pre>';
print_r($args);
echo '</pre>';
die();
// Check for & assign any parameters which require special handling or setting.
$args['date_query'] = array();
// Set before into date query. Date query must be specified as an array of an array.
if ( isset( $registered['before'], $request['before'] ) ) {
$args['date_query'][0]['before'] = $request['before'];
}
// Set after into date query. Date query must be specified as an array of an array.
if ( isset( $registered['after'], $request['after'] ) ) {
$args['date_query'][0]['after'] = $request['after'];
}
// Ensure our per_page parameter overrides any provided posts_per_page filter.
if ( isset( $registered['per_page'] ) ) {
$args['posts_per_page'] = $request['per_page'];
}
if ( isset( $registered['sticky'], $request['sticky'] ) ) {
$sticky_posts = get_option( 'sticky_posts', array() );
if ( ! is_array( $sticky_posts ) ) {
$sticky_posts = array();
}
if ( $request['sticky'] ) {
/*
* As post__in will be used to only get sticky posts,
* we have to support the case where post__in was already
* specified.
*/
$args['post__in'] = $args['post__in'] ? array_intersect( $sticky_posts, $args['post__in'] ) : $sticky_posts;
/*
* If we intersected, but there are no post IDs in common,
* WP_Query won't return "no posts" for post__in = array()
* so we have to fake it a bit.
*/
if ( ! $args['post__in'] ) {
$args['post__in'] = array( 0 );
}
} elseif ( $sticky_posts ) {
/*
* As post___not_in will be used to only get posts that
* are not sticky, we have to support the case where post__not_in
* was already specified.
*/
$args['post__not_in'] = array_merge( $args['post__not_in'], $sticky_posts );
}
}
// Force the post_type argument, since it's not a user input variable.
$args['post_type'] = array('post','book');
/**
* Filters the query arguments for a request.
*
* Enables adding extra arguments or setting defaults for a post collection request.
*
* @since 4.7.0
*
* @link https://developer.wordpress.org/reference/classes/wp_query/
*
* @param array $args Key value array of query var to query value.
* @param WP_REST_Request $request The request used.
*/
$args = apply_filters( "rest_{$this->post_type}_query", $args, $request );
$query_args = $this->prepare_items_query( $args, $request );
$taxonomies = wp_list_filter( get_object_taxonomies( $this->post_type, 'objects' ), array( 'show_in_rest' => true ) );
if ( ! empty( $request['tax_relation'] ) ) {
$query_args['tax_query'] = array( 'relation' => $request['tax_relation'] );
}
foreach ( $taxonomies as $taxonomy ) {
$base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name;
$tax_exclude = $base . '_exclude';
if ( ! empty( $request[ $base ] ) ) {
$query_args['tax_query'][] = array(
'taxonomy' => $taxonomy->name,
'field' => 'term_id',
'terms' => $request[ $base ],
'include_children' => false,
);
}
if ( ! empty( $request[ $tax_exclude ] ) ) {
$query_args['tax_query'][] = array(
'taxonomy' => $taxonomy->name,
'field' => 'term_id',
'terms' => $request[ $tax_exclude ],
'include_children' => false,
'operator' => 'NOT IN',
);
}
}
$posts_query = new WP_Query();
$query_result = $posts_query->query( $query_args );
// Allow access to all password protected posts if the context is edit.
if ( 'edit' === $request['context'] ) {
add_filter( 'post_password_required', '__return_false' );
}
$posts = array();
foreach ( $query_result as $post ) {
if ( ! $this->check_read_permission( $post ) ) {
continue;
}
$data = $this->prepare_item_for_response( $post, $request );
$posts[] = $this->prepare_response_for_collection( $data );
}
// Reset filter.
if ( 'edit' === $request['context'] ) {
remove_filter( 'post_password_required', '__return_false' );
}
$page = (int) $query_args['paged'];
$total_posts = $posts_query->found_posts;
if ( $total_posts < 1 ) {
// Out-of-bounds, run the query again without LIMIT for total count.
unset( $query_args['paged'] );
$count_query = new WP_Query();
$count_query->query( $query_args );
$total_posts = $count_query->found_posts;
}
$max_pages = ceil( $total_posts / (int) $posts_query->query_vars['posts_per_page'] );
// Có 40 bài viết và link như sau http://localhost/wordpress/wp-json/wp/v2/posts?context=view&page=1&per_page=10
// <pre>4.0</pre>
if ( $page > $max_pages && $total_posts > 0 ) {
return new WP_Error(
'rest_post_invalid_page_number',
__( 'The page number requested is larger than the number of pages available.' ),
array( 'status' => 400 )
);
}
$response = rest_ensure_response( $posts );
$response->header( 'X-WP-Total', (int) $total_posts );
$response->header( 'X-WP-TotalPages', (int) $max_pages );
$request_params = $request->get_query_params();
// array (
// 'context' => 'view',
// 'page' => 2,
// 'per_page' => 2,
// )
$base = add_query_arg( urlencode_deep( $request_params ), rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ) );
if ( $page > 1 ) {
$prev_page = $page - 1;
if ( $prev_page > $max_pages ) {
$prev_page = $max_pages;
}
$prev_link = add_query_arg( 'page', $prev_page, $base );
$response->link_header( 'prev', $prev_link );
}
if ( $max_pages > $page ) {
$next_page = $page + 1;
$next_link = add_query_arg( 'page', $next_page, $base );
$response->link_header( 'next', $next_link );
}
return $response;
}