[API] Resource Schema (ok)

https://developer.wordpress.org/rest-api/extending-the-rest-api/schema/

http://localhost/api/wp-json/my-namespace/v1/comments

<?php
// Register our routes.
function prefix_register_my_comment_route() {
  register_rest_route('my-namespace/v1', '/comments', array(
    // Notice how we are registering multiple endpoints the 'schema' equates to an OPTIONS request.
    array(
      'methods'  => 'GET',
      'callback' => 'prefix_get_comment_sample',
    ),
    // Register our schema callback.
    'schema' => 'prefix_get_comment_schema',
  ));
}
add_action('rest_api_init', 'prefix_register_my_comment_route');
/**
 * Grabs the five most recent comments and outputs them as a rest response.
 *
 * @param WP_REST_Request $request Current request.
 */
function prefix_get_comment_sample($request) {
  $args = array(
    'number' => 5,
  );
  $comments = get_comments($args);
  $data = array();
  if (empty($comments)) {
    return rest_ensure_response($data);
  }
  foreach ($comments as $comment) {
    $response = prefix_rest_prepare_comment($comment, $request);
    $data[]   = prefix_prepare_for_collection($response);
  }
  // Return all of our comment response data.
  return rest_ensure_response($data);
}
/**
 * Matches the comment data to the schema we want.
 *
 * @param WP_Comment $comment The comment object whose response is being prepared.
 */
function prefix_rest_prepare_comment($comment, $request) {
  $comment_data = array();
  $schema = prefix_get_comment_schema();
  // We are also renaming the fields to more understandable names.
  if (isset($schema['properties']['id'])) {
    $comment_data['id'] = (int) $comment->comment_ID;
  }
  if (isset($schema['properties']['author'])) {
    $comment_data['author'] = (int) $comment->user_id;
  }
  if (isset($schema['properties']['content'])) {
    $comment_data['content'] = apply_filters('comment_text', $comment->comment_content, $comment);
  }
  return rest_ensure_response($comment_data);
}
/**
 * Prepare a response for inserting into a collection of responses.
 *
 * This is copied from WP_REST_Controller class in the WP REST API v2 plugin.
 *
 * @param WP_REST_Response $response Response object.
 * @return array Response data, ready for insertion into collection data.
 */
function prefix_prepare_for_collection($response) {
  if (!($response instanceof WP_REST_Response)) {
    return $response;
  }
  $data  = (array) $response->get_data();
  $links = rest_get_server()::get_compact_response_links($response);
  if (!empty($links)) {
    $data['_links'] = $links;
  }
  return $data;
}
/**
 * Get our sample schema for comments.
 */
function prefix_get_comment_schema() {
  $schema = array(
    // This tells the spec of JSON Schema we are using which is draft 4.
    '$schema'    => 'http://json-schema.org/draft-04/schema#',
    // The title property marks the identity of the resource.
    'title'      => 'comment',
    'type'       => 'object',
    // In JSON Schema you can specify object properties in the properties attribute.
    'properties' => array(
      'id'      => array(
        'description' => esc_html__('Unique identifier for the object.', 'my-textdomain'),
        'type'        => 'integer',
        'context'     => array('view', 'edit', 'embed'),
        'readonly'    => true,
      ),
      'author'  => array(
        'description' => esc_html__('The id of the user object, if author was a user.', 'my-textdomain'),
        'type'        => 'integer',
      ),
      'content' => array(
        'description' => esc_html__('The content for the object.', 'my-textdomain'),
        'type'        => 'string',
      ),
    ),
  );
  return $schema;
}
?>

Nếu bạn nhận thấy, mỗi tài nguyên nhận xét hiện khớp với lược đồ mà chúng tôi đã chỉ định. Chúng tôi đã thực hiện chuyển đổi này trong prefix_rest_prepare_comment (). Bằng cách tạo giản đồ cho các tài nguyên của mình, giờ đây chúng ta có thể xem lược đồ này bằng cách đưa ra các yêu cầu TÙY CHỌN. Tại sao điều này lại hữu ích? Nếu chúng tôi muốn các ngôn ngữ khác, chẳng hạn như JavaScript, để diễn giải dữ liệu của chúng tôi và xác thực dữ liệu từ điểm cuối của chúng tôi, thì JavaScript sẽ cần biết dữ liệu của chúng tôi được cấu trúc như thế nào. Khi chúng tôi cung cấp lược đồ, chúng tôi mở ra cánh cửa cho các tác giả khác và chính chúng tôi xây dựng dựa trên các điểm cuối của chúng tôi một cách nhất quán.

Schema cung cấp dữ liệu có thể đọc được của máy, vì vậy bất kỳ thứ gì có thể đọc được JSON đều có thể hiểu loại dữ liệu mà nó đang xem. Khi chúng tôi xem chỉ mục API bằng cách đưa ra yêu cầu GET tới https://ourawesomesite.com/wp-json/, chúng tôi sẽ được trả về giản đồ API của mình, cho phép người khác viết thư viện ứng dụng khách để diễn giải dữ liệu của chúng tôi. Quá trình đọc dữ liệu lược đồ này được gọi là quá trình khám phá. Khi chúng tôi đã cung cấp lược đồ cho một tài nguyên, chúng tôi làm cho tài nguyên đó có thể khám phá được thông qua các yêu cầu OPTIONS tới tuyến đường đó. Hiển thị lược đồ tài nguyên chỉ là một phần của câu đố giản đồ của chúng tôi. Chúng tôi cũng muốn sử dụng lược đồ cho các đối số đã đăng ký của chúng tôi.

Argument Schema

Khi chúng tôi đăng ký các đối số yêu cầu cho một điểm cuối, chúng tôi cũng có thể sử dụng Lược đồ JSON để cung cấp cho chúng tôi dữ liệu về các đối số nên là gì. Điều này cho phép chúng tôi viết các thư viện xác thực có thể được sử dụng lại khi các điểm cuối của chúng tôi mở rộng. Schema có nhiều công việc hơn trước, nhưng nếu bạn định viết một ứng dụng sản xuất sẽ phát triển, bạn chắc chắn nên cân nhắc sử dụng schema. Hãy xem một ví dụ về việc sử dụng lược đồ đối số và xác thực.

Trong ví dụ trên, chúng tôi đã rút gọn khỏi việc sử dụng tên 'my-arg'. Chúng tôi có thể sử dụng các hàm xác nhận và làm sạch này cho bất kỳ đối số nào khác phải là một chuỗi mà chúng tôi đã chỉ định lược đồ. Khi cơ sở mã và điểm cuối của bạn phát triển, lược đồ sẽ giúp giữ cho mã của bạn nhẹ và có thể bảo trì. Nếu không có lược đồ, bạn có thể xác thực và làm sạch, tuy nhiên sẽ khó khăn hơn để theo dõi xem chức năng nào nên xác thực cái gì. Bằng cách thêm lược đồ vào các đối số yêu cầu, chúng tôi cũng có thể hiển thị lược đồ đối số của mình cho các máy khách, do đó, các thư viện xác thực có thể được xây dựng phía máy khách có thể giúp hiệu suất bằng cách ngăn các yêu cầu không hợp lệ được gửi đến API.

<?php
// Register our routes.
function prefix_register_my_arg_route() {
  register_rest_route('my-namespace/v1', '/schema-arg', array(
    // Here we register our endpoint.
    array(
      'methods'  => 'GET',
      'callback' => 'prefix_get_item',
      'args'     => prefix_get_endpoint_args(),
    ),
  ));
}
// Hook registration into 'rest_api_init' hook.
add_action('rest_api_init', 'prefix_register_my_arg_route');
/**
 * Returns the request argument `my-arg` as a rest response.
 *
 * @param WP_REST_Request $request Current request.
 */
function prefix_get_item($request) {
  // If we didn't use required in the schema this would throw an error when my arg is not set.
  return rest_ensure_response($request['my-arg']);
}
/**
 * Get the argument schema for this example endpoint.
 */
function prefix_get_endpoint_args() {
  $args = array();
  // Here we add our PHP representation of JSON Schema.
  $args['my-arg'] = array(
    'description'       => esc_html__('This is the argument our endpoint returns.', 'my-textdomain'),
    'type'              => 'string',
    'validate_callback' => 'prefix_validate_my_arg',
    'sanitize_callback' => 'prefix_sanitize_my_arg',
    'required'          => true,
  );
  return $args;
}
/**
 * Our validation callback for `my-arg` parameter.
 *
 * @param mixed           $value   Value of the my-arg parameter.
 * @param WP_REST_Request $request Current request object.
 * @param string          $param   The name of the parameter in this case, 'my-arg'.
 * @return true|WP_Error True if the data is valid, WP_Error otherwise.
 */
function prefix_validate_my_arg($value, $request, $param) {
  $attributes = $request->get_attributes();
  if (isset($attributes['args'][$param])) {
    $argument = $attributes['args'][$param];
    // Check to make sure our argument is a string.
    if ('string' === $argument['type'] && !is_string($value)) {
      return new WP_Error('rest_invalid_param', sprintf(esc_html__('%1$s is not of type %2$s', 'my-textdomain'), $param, 'string'), array('status' => 400));
    }
  } else {
    // This code won't execute because we have specified this argument as required.
    // If we reused this validation callback and did not have required args then this would fire.
    return new WP_Error('rest_invalid_param', sprintf(esc_html__('%s was not registered as a request argument.', 'my-textdomain'), $param), array('status' => 400));
  }
  // If we got this far then the data is valid.
  return true;
}
/**
 * Our sanitization callback for `my-arg` parameter.
 *
 * @param mixed           $value   Value of the my-arg parameter.
 * @param WP_REST_Request $request Current request object.
 * @param string          $param   The name of the parameter in this case, 'my-arg'.
 * @return mixed|WP_Error The sanitize value, or a WP_Error if the data could not be sanitized.
 */
function prefix_sanitize_my_arg($value, $request, $param) {
  $attributes = $request->get_attributes();
  if (isset($attributes['args'][$param])) {
    $argument = $attributes['args'][$param];
    // Check to make sure our argument is a string.
    if ('string' === $argument['type']) {
      return sanitize_text_field($value);
    }
  } else {
    // This code won't execute because we have specified this argument as required.
    // If we reused this validation callback and did not have required args then this would fire.
    return new WP_Error('rest_invalid_param', sprintf(esc_html__('%s was not registered as a request argument.', 'my-textdomain'), $param), array('status' => 400));
  }
  // If we got this far then something went wrong don't use user input.
  return new WP_Error('rest_api_sad', esc_html__('Something went terribly wrong.', 'my-textdomain'), array('status' => 500));
}
?>

Summary

Lược đồ có thể có vẻ ngớ ngẩn ở các điểm và có thể là công việc không cần thiết, nhưng nếu bạn muốn các điểm cuối có thể bảo trì, có thể khám phá và dễ dàng mở rộng, thì điều cần thiết là sử dụng lược đồ. Schema cũng giúp tự ghi lại các điểm cuối của bạn cho cả con người và máy tính!

JSON Schema Basics

WordPress triển khai trình xác thực sử dụng tập hợp con của đặc tả lược đồ JSON Phiên bản 4. Bạn nên đọc RFC để hiểu sâu hơn về cách hoạt động của Lược đồ JSON, nhưng bài viết này sẽ mô tả những điều cơ bản về Lược đồ JSON và những tính năng nào mà WordPress hỗ trợ.

API

API REST xác định hai hàm chính để sử dụng Lược đồ JSON: rest_validate_value_from_schema và rest_sanifying_value_from_schema. Cả hai hàm đều chấp nhận dữ liệu yêu cầu làm tham số đầu tiên, định nghĩa giản đồ của tham số làm tham số thứ hai và tùy chọn tên của tham số làm tham số thứ ba. Hàm xác thực trả về true hoặc một trường hợp WP_Error tùy thuộc vào việc dữ liệu có xác thực thành công so với lược đồ hay không. Hàm sanitize trả về một dạng dữ liệu được làm sạch được chuyển đến hàm hoặc một phiên bản WP_Error nếu dữ liệu không thể được làm sạch một cách an toàn.

Khi gọi các hàm này, bạn nên lưu ý luôn xác thực dữ liệu trước tiên bằng rest_validate_value_from_schema, sau đó nếu hàm đó trả về true, hãy làm sạch dữ liệu bằng rest_sanizing_value_from_schema. Không sử dụng cả hai có thể mở ra điểm cuối của bạn cho các lỗ hổng bảo mật.

Nếu điểm cuối của bạn được triển khai bằng cách sử dụng lớp con của WP_REST_Controller, thì phương thức WP_REST_Controller :: get_endpoint_args_for_item_schema sẽ tự động đánh dấu các đối số của bạn là sử dụng các lệnh gọi lại xác thực và khử trùng tích hợp sẵn. Do đó, không cần phải chỉ định thủ công các lệnh gọi lại.

Nếu điểm cuối của bạn không tuân theo mẫu lớp bộ điều khiển, các args được trả về từ WP_REST_Controller :: get_collection_params () hoặc bất kỳ trường hợp nào khác mà các lệnh gọi lại không được chỉ định, đối tượng WP_REST_Request sẽ áp dụng sanitization và xác thực bằng cách sử dụng hàm rest_parse_request_arg. Quan trọng là, điều này chỉ được áp dụng khi sanitize_callback không được xác định. Do đó, nếu bạn chỉ định sanitize_callback tùy chỉnh cho định nghĩa đối số của mình thì xác thực lược đồ JSON tích hợp sẵn sẽ không áp dụng. Nếu bạn cần xác thực này, bạn nên chỉ định rest_validate_request_arg theo cách thủ công làm validate_callback trong định nghĩa đối số của bạn.

Schema Documents

A basic schema document consists of a few properties.

$ schema Một tham chiếu đến một meta schema mô tả phiên bản của đặc tả mà tài liệu đang sử dụng. title Tiêu đề của lược đồ. Thông thường đây là nhãn có thể đọc được của con người, nhưng trong WordPress thì đây là chuỗi có thể đọc được bằng máy. Ví dụ: điểm cuối của bài đăng có tiêu đề là "bài đăng". Các bình luận có tiêu đề là ‘comment’. loại Điều này đề cập đến loại giá trị được mô tả. Đây có thể là một trong bảy kiểu nguyên thủy. Trong WordPress, kiểu cấp cao nhất hầu như luôn luôn là một đối tượng, ngay cả đối với các điểm cuối bộ sưu tập trả về một mảng đối tượng. thuộc tính Danh sách các thuộc tính đã biết có trong đối tượng và định nghĩa của chúng. Bản thân mỗi định nghĩa thuộc tính cũng là một lược đồ, nhưng không có thuộc tính cấp cao nhất $ schema, được mô tả chính xác hơn là một lược đồ con.

Primitive Types

Lược đồ JSON xác định danh sách bảy kiểu nguyên thủy được phép.

string Một giá trị chuỗi. null Giá trị null. số Bất kỳ số nào. Số thập phân được phép. Tương đương với một float trong PHP. số nguyên Một số, nhưng số thập phân hoặc số mũ không được phép. boolean Một giá trị đúng hoặc sai. mảng Một danh sách các giá trị. Điều này tương đương với một mảng JavaScript. Trong PHP, đây được gọi là một mảng số hoặc một mảng không có khóa xác định. đối tượng Một bản đồ các khóa đến các giá trị. Điều này tương đương với một đối tượng JavaScript. Trong PHP, đây được gọi là một mảng kết hợp hoặc một mảng với các khóa được xác định.

Kiểu nguyên thủy của giá trị được chỉ định bằng cách sử dụng từ khóa type. Ví dụ, đây là cách bạn định nghĩa một giá trị chuỗi bằng Lược đồ JSON.

array(
    'type' => 'string',
);

Lược đồ JSON cho phép xác định các giá trị có thể là nhiều kiểu. Ví dụ, đây là cách bạn định nghĩa một giá trị có thể là một chuỗi hoặc một boolean.

array(
    'type' => array( 'boolean', 'string' ),  
);

Type Juggling

Bởi vì API REST của WordPress chấp nhận dữ liệu được mã hóa của biểu mẫu URL cả trong phần nội dung POST hoặc dưới dạng phần truy vấn của URL, nhiều loại nguyên thủy thực hiện trộn loại để chuyển đổi các giá trị chuỗi này thành các loại gốc thích hợp của chúng.

Chuỗi Chỉ cho phép các chuỗi theo is_string. null Chỉ chấp nhận null được nhập đúng. Điều này có nghĩa là không thể gửi giá trị rỗng trong URL hoặc dưới dạng nội dung bài đăng được mã hóa biểu mẫu URL, phải sử dụng nội dung yêu cầu JSON. số Floats, số nguyên và chuỗi vượt qua is_numeric được phép. Giá trị sẽ được chuyển thành một float. số nguyên Số nguyên hoặc chuỗi có thể được chuyển thành một số thực có phần phân số tương đương với 0. boolean Boolean, các số nguyên 0 và 1 hoặc các chuỗi "0", "1", "false" và "true". 0 được coi là sai và 1 được coi là đúng. mảng Mảng số theo wp_is_numeric_array hoặc một chuỗi. Nếu chuỗi được phân tách bằng dấu phẩy thì nó sẽ được tách thành một mảng, ngược lại nó sẽ là một mảng chứa giá trị chuỗi. Ví dụ: "red, yellow" trở thành aray ("red", "yellow") và "blue" trở thành array ("blue"). đối tượng Một mảng, một đối tượng stdClass, một đối tượng triển khai JsonSerializable hoặc một chuỗi rỗng. Giá trị sẽ được chuyển đổi thành một mảng PHP gốc.

Khi sử dụng nhiều loại, các loại sẽ được đánh giá theo thứ tự được chỉ định. Điều này có thể ảnh hưởng đến dữ liệu đã làm sạch mà điểm cuối API REST của bạn nhận được. Ví dụ: trong ví dụ trước, nếu giá trị được gửi là "1", nó sẽ được làm sạch thành giá trị thực của boolean. Tuy nhiên, nếu thứ tự bị lật, giá trị sẽ vẫn là chuỗi "1".

Format

Last updated