---
description: >-
  https://developer.wordpress.org/rest-api/extending-the-rest-api/adding-custom-endpoints/
---

# \[API] Adding Custom Endpoints

API REST của WordPress không chỉ là một tập hợp các tuyến đường mặc định. Nó cũng là một công cụ để tạo các tuyến đường và điểm cuối tùy chỉnh. Giao diện người dùng WordPress cung cấp một tập hợp các ánh xạ URL mặc định, nhưng các công cụ được sử dụng để tạo chúng (ví dụ: API Viết lại, cũng như các lớp truy vấn: WP\_Query, WP\_User, v.v.) cũng có sẵn để tạo ánh xạ URL của riêng bạn, hoặc truy vấn tùy chỉnh.

Tài liệu này trình bày chi tiết cách tạo một tuyến đường hoàn toàn tùy chỉnh, với các điểm cuối của riêng nó. Trước tiên, chúng tôi sẽ làm việc thông qua một ví dụ ngắn, sau đó mở rộng nó ra mẫu bộ điều khiển đầy đủ như được sử dụng trong nội bộ.

### Bare Basics <a href="#bare-basics" id="bare-basics"></a>

Vì vậy, bạn muốn thêm điểm cuối tùy chỉnh vào API? Tuyệt diệu! Hãy bắt đầu với một ví dụ đơn giản. Hãy bắt đầu với một hàm đơn giản giống như sau:

Để cung cấp điều này thông qua API, chúng tôi cần đăng ký một tuyến đường. Điều này yêu cầu API phản hồi một yêu cầu nhất định với chức năng của chúng tôi. Chúng tôi thực hiện việc này thông qua một hàm có tên register\_rest\_route, hàm này sẽ được gọi trong lệnh gọi lại trên rest\_api\_init để tránh thực hiện thêm công việc khi không tải API.

Chúng ta cần chuyển ba thứ vào register\_rest\_route: không gian tên, tuyến đường chúng ta muốn và các tùy chọn. Chúng ta sẽ quay lại vùng tên sau một chút, nhưng bây giờ, hãy chọn myplugin / v1. Chúng tôi sẽ có tuyến đường khớp với bất kỳ thứ gì với / author / {id}, trong đó {id} là một số nguyên.

```
<?php
/**
 * Grab latest post title by an author!
 *
 * @param array $data Options for the function.
 * @return string|null Post title for the latest,
 * or null if none.
 */
function my_awesome_func($data) {
  $posts = get_posts(
    array(
      'author' => $data['id'],
    )
  );
  if (empty($posts)) {
    return null;
  }
  return $posts[0]->post_title;
}
add_action('rest_api_init', function () {
  register_rest_route('myplugin/v1', '/author/(?P<id>\d+)', array(
    'methods'  => 'GET',
    'callback' => 'my_awesome_func',
  ));
});
?>
```

#### Chú ý: Ta hay thay phương thức 'GET' bằng cách sau WP\_REST\_Server::READABLE

Hiện tại, chúng tôi chỉ đăng ký một điểm cuối cho tuyến đường. Thuật ngữ "tuyến đường" đề cập đến URL, trong khi "điểm cuối" đề cập đến hàm đằng sau nó tương ứng với một phương thức và một URL (để biết thêm thông tin, hãy xem Bảng chú giải thuật ngữ).

Mỗi tuyến đường có thể có bất kỳ số lượng điểm cuối nào và đối với mỗi điểm cuối, bạn có thể xác định các phương thức HTTP được phép, một hàm gọi lại để phản hồi yêu cầu và một lệnh gọi lại quyền để tạo các quyền tùy chỉnh. Ngoài ra, bạn có thể xác định các trường được phép trong yêu cầu và đối với mỗi trường, chỉ định một giá trị mặc định, một lệnh gọi lại làm sạch, một lệnh gọi lại xác thực và liệu trường có được yêu cầu hay không.

#### Namespacing <a href="#namespacing" id="namespacing"></a>

Không gian tên là phần đầu tiên của URL cho điểm cuối. Chúng nên được sử dụng làm tiền tố nhà cung cấp / gói để ngăn chặn xung đột giữa các tuyến tùy chỉnh. Không gian tên cho phép hai plugin thêm một tuyến đường có cùng tên, với các chức năng khác nhau.

Không gian tên nói chung phải tuân theo mẫu của nhà cung cấp / v1, trong đó nhà cung cấp thường là plugin hoặc slug chủ đề của bạn và v1 đại diện cho phiên bản đầu tiên của API. Nếu bạn cần phải phá vỡ khả năng tương thích với các điểm cuối mới, thì bạn có thể nâng nó lên phiên bản v2.

Tình huống trên, hai tuyến đường có cùng tên, từ hai plugin khác nhau, yêu cầu tất cả các nhà cung cấp phải sử dụng một không gian tên duy nhất. Không làm như vậy tương tự như việc không sử dụng tiền tố hàm của nhà cung cấp, tiền tố lớp và / hoặc không gian tên lớp trong chủ đề hoặc plugin, điều này rất tệ.

Một lợi ích bổ sung của việc sử dụng không gian tên là khách hàng có thể phát hiện hỗ trợ cho API tùy chỉnh của bạn. Chỉ mục API liệt kê các không gian tên có sẵn trên một trang web:

```
{
  "name": "WordPress Site",
  "description": "Just another WordPress site",
  "url": "http://example.com/",
  "namespaces": [
    "wp/v2",
    "vendor/v1",
    "myplugin/v1",
    "myplugin/v2",
  ]
}
```

Nếu khách hàng muốn kiểm tra xem API của bạn có tồn tại trên một trang web hay không, họ có thể kiểm tra danh sách này. (Để biết thêm thông tin, hãy xem hướng dẫn [~~Khám phá.~~](https://developer.wordpress.org/rest-api/using-the-rest-api/discovery/))

#### Arguments <a href="#arguments" id="arguments"></a>

Theo mặc định, các tuyến nhận tất cả các đối số được chuyển vào từ yêu cầu. Các tham số này được hợp nhất thành một tập hợp các tham số, sau đó được thêm vào đối tượng Yêu cầu, được chuyển vào dưới dạng tham số đầu tiên cho điểm cuối của bạn:

```
<?php
function my_awesome_func(WP_REST_Request $request) {
  // You can access parameters via direct array access on the object:
  $param = $request['some_param'];
  // Or via the helper method:
  $param = $request->get_param('some_param');
  // You can get the combined, merged set of parameters:
  $parameters = $request->get_params();
  // The individual sets of parameters are also available, if needed:
  $parameters = $request->get_url_params();
  $parameters = $request->get_query_params();
  $parameters = $request->get_body_params();
  $parameters = $request->get_json_params();
  $parameters = $request->get_default_params();
  // Uploads aren't merged in, but can be accessed separately:
  $parameters = $request->get_file_params();
}
?>
```

(Để tìm hiểu chính xác cách hợp nhất các tham số, hãy kiểm tra nguồn của WP\_REST\_Request :: get\_parameter\_order (); thứ tự cơ bản là nội dung, truy vấn, URL, sau đó là mặc định.)

Thông thường, bạn sẽ nhận được mọi thông số được đưa vào không thay đổi. Tuy nhiên, bạn có thể đăng ký các đối số của mình khi đăng ký tuyến đường của mình, điều này cho phép bạn chạy sanitization và xác thực trên các đối số này.

Nếu yêu cầu có bộ tiêu đề Content-type: application / json và JSON hợp lệ trong phần thân, get\_json\_params () sẽ trả về phần nội dung JSON được phân tích cú pháp dưới dạng một mảng liên kết.

Các đối số được định nghĩa là một bản đồ trong các nhóm khóa cho mỗi điểm cuối (bên cạnh tùy chọn gọi lại của bạn). Bản đồ này sử dụng tên của đối số của khóa, với giá trị là bản đồ các tùy chọn cho đối số đó. Mảng này có thể chứa một khóa cho mặc định, bắt buộc, sanitize\_callback và validate\_callback.

default: Được sử dụng làm giá trị mặc định cho đối số, nếu không có đối số nào được cung cấp. Bắt buộc: Nếu được xác định là true và không có giá trị nào được chuyển cho đối số đó, thì một lỗi sẽ được trả về. Không có hiệu lực nếu một giá trị mặc định được đặt, vì đối số sẽ luôn có một giá trị. validate\_callback: Được sử dụng để truyền một hàm sẽ được truyền giá trị của đối số. Hàm đó sẽ trả về true nếu giá trị hợp lệ và false nếu không. sanitize\_callback: Được sử dụng để truyền một hàm được sử dụng để làm sạch giá trị của đối số trước khi chuyển nó đến lệnh gọi lại chính.

Sử dụng sanitize\_callback và validate\_callback cho phép lệnh gọi lại chính chỉ hoạt động để xử lý yêu cầu và chuẩn bị dữ liệu để được trả lại bằng cách sử dụng lớp WP\_REST\_Response. Bằng cách sử dụng hai lệnh gọi lại này, bạn sẽ có thể an toàn cho rằng đầu vào của mình là hợp lệ và an toàn khi xử lý.

Lấy ví dụ trước của chúng tôi, chúng tôi có thể đảm bảo tham số được truyền vào luôn là một số:

Bạn cũng có thể chuyển một tên hàm vào validate\_callback, nhưng việc truyền trực tiếp một số hàm như is\_numeric sẽ không chỉ đưa ra cảnh báo về việc có các tham số bổ sung được truyền cho nó mà còn trả về NULL khiến hàm gọi lại được gọi với dữ liệu không hợp lệ. Chúng tôi hy vọng cuối cùng sẽ giải quyết được vấn đề này trong lõi WordPress.

Chúng tôi cũng có thể sử dụng một cái gì đó như 'sanitize\_callback' => 'absint' để thay thế, nhưng xác thực sẽ gây ra lỗi, cho phép khách hàng hiểu họ đang làm gì sai. Sanitization hữu ích khi bạn muốn thay đổi dữ liệu đang được nhập hơn là tạo ra một lỗi (chẳng hạn như HTML không hợp lệ).

#### Return Value  <a href="#return-value" id="return-value"></a>

Sau khi lệnh gọi lại của bạn được gọi, giá trị trả về sau đó được chuyển đổi thành JSON và được trả lại cho máy khách. Điều này cho phép bạn trả về cơ bản bất kỳ dạng dữ liệu nào. Trong ví dụ của chúng tôi ở trên, chúng tôi đang trả về một chuỗi hoặc null, được API tự động xử lý và chuyển đổi thành JSON.

Giống như bất kỳ chức năng WordPress nào khác, bạn cũng có thể trả về một phiên bản WP\_Error. Thông tin lỗi này sẽ được chuyển đến máy khách, cùng với mã trạng thái Lỗi dịch vụ nội bộ 500. Bạn có thể tùy chỉnh thêm lỗi của mình bằng cách đặt tùy chọn trạng thái trong dữ liệu phiên bản WP\_Error thành mã, chẳng hạn như 400 đối với dữ liệu đầu vào không hợp lệ. Lấy ví dụ của chúng tôi từ trước, bây giờ chúng tôi có thể trả về một trường hợp lỗi:

```
<?php
/**
 * Grab latest post title by an author!
 *
 * @param array $data Options for the function.
 * @return string|null Post title for the latest,
 * or null if none.
 */
function my_awesome_func($data) {
  $posts = get_posts(array(
    'author' => $data['id'],
  ));
  if (empty($posts)) {
    return new WP_Error('no_author', 'Invalid author', array('status' => 404));
  }
  return $posts[0]->post_title;
}
?>
```

Khi một tác giả không có bất kỳ bài đăng nào thuộc về họ, điều này sẽ trả lại lỗi 404 Not Found cho khách hàng:

```
HTTP/1.1 404 Not Found
 
[{
   "code": "no_author",
   "message": "Invalid author",
   "data": { "status": 404 }
}]
```

Để sử dụng nâng cao hơn, bạn có thể trả về đối tượng WP\_REST\_Response. Đối tượng này "bao bọc" dữ liệu nội dung bình thường, nhưng cho phép bạn trả về mã trạng thái tùy chỉnh hoặc tiêu đề tùy chỉnh. Bạn cũng có thể thêm liên kết vào câu trả lời của mình. Cách nhanh nhất để sử dụng điều này là thông qua hàm tạo:

```
<?php
$data = array( 'some', 'response', 'data' );
// Create the response object
$response = new WP_REST_Response( $data );
// Add a custom status code
$response->set_status( 201 );
// Add a custom header
$response->header( 'Location', 'http://localhost/api/' );
?>
```

Khi gói các lệnh gọi lại hiện có, bạn phải luôn sử dụng rest\_ensure\_response () trên giá trị trả về. Thao tác này sẽ lấy dữ liệu thô được trả về từ một điểm cuối và tự động biến nó thành WP\_REST\_Response cho bạn. (Lưu ý rằng WP\_Error không được chuyển đổi thành WP\_REST\_Response để cho phép xử lý lỗi thích hợp.)

Quan trọng là, lệnh gọi lại của tuyến API REST phải luôn trả về dữ liệu; nó không nên cố gắng gửi chính nội dung phản hồi. Điều này đảm bảo rằng quá trình xử lý bổ sung mà máy chủ REST API thực hiện, như xử lý liên kết / nhúng, gửi tiêu đề, v.v. sẽ diễn ra. Nói cách khác, không gọi die (wp\_json\_encode ($ data)); hoặc wp\_send\_json ($ data). Kể từ phiên bản WordPress 5.5, thông báo \_doing\_it\_wrong được đưa ra nếu họ hàm wp\_send\_json () được sử dụng trong một yêu cầu API REST.

#### Permissions Callback <a href="#permissions-callback" id="permissions-callback"></a>

Bạn cũng phải đăng ký một quyền gọi lại cho điểm cuối. Đây là một chức năng kiểm tra xem người dùng có thể thực hiện hành động (đọc, cập nhật, v.v.) trước khi gọi lại thực sự được gọi hay không. Điều này cho phép API cho khách hàng biết họ có thể thực hiện những hành động nào trên một URL nhất định mà không cần thử yêu cầu trước.

Lệnh gọi lại này có thể được đăng ký dưới dạng allow\_callback, một lần nữa trong các tùy chọn điểm cuối bên cạnh tùy chọn gọi lại của bạn. Lệnh gọi lại này sẽ trả về một boolean hoặc một phiên bản WP\_Error. Nếu hàm này trả về true, phản hồi sẽ được xử lý. Nếu nó trả về false, một thông báo lỗi mặc định sẽ được trả lại và yêu cầu sẽ không được tiếp tục xử lý. Nếu nó trả về một WP\_Error, lỗi đó sẽ được trả lại cho máy khách.

Lệnh gọi lại quyền được chạy sau khi xác thực từ xa, xác thực người dùng hiện tại. Điều này có nghĩa là bạn có thể sử dụng current\_user\_can để kiểm tra xem người dùng đã được xác thực có khả năng thích hợp cho hành động hay không hoặc bất kỳ kiểm tra nào khác dựa trên ID người dùng hiện tại. Nếu có thể, bạn nên luôn sử dụng current\_user\_can; thay vì kiểm tra xem người dùng đã đăng nhập (xác thực) hay chưa, hãy kiểm tra xem họ có thể thực hiện hành động (ủy quyền) hay không.

Sau khi đăng ký allow\_callback, bạn sẽ cần xác thực các yêu cầu của mình (ví dụ: bằng cách bao gồm tham số nonce) nếu không bạn sẽ nhận được lỗi rest\_forbidden. Xem Xác thực để biết thêm chi tiết.

Tiếp tục với ví dụ trước của chúng tôi, chúng tôi có thể làm cho nó để chỉ những người chỉnh sửa trở lên mới có thể xem dữ liệu tác giả này. Chúng tôi có thể kiểm tra một số khả năng khác nhau ở đây, nhưng tốt nhất là edit\_others\_posts, đây thực sự là cốt lõi của trình soạn thảo. Để làm điều này, chúng tôi chỉ cần gọi lại ở đây:

```
<?php
add_action('rest_api_init', function () {
  register_rest_route('myplugin/v1', '/author/(?P<id>\d+)', array(
    'methods'             => 'GET',
    'callback'            => 'my_awesome_func',
    'args'                => array(
      'id' => array(
        'validate_callback' => 'is_numeric',
      ),
    ),
    'permission_callback' => function () {
      return current_user_can('edit_others_posts');
    },
  ));
});
?>
```

Lưu ý rằng lệnh gọi lại quyền cũng nhận đối tượng Yêu cầu làm tham số đầu tiên, vì vậy bạn có thể kiểm tra dựa trên đối số yêu cầu nếu cần.

Kể từ phiên bản WordPress 5.5, nếu không cung cấp allow\_callback, REST API sẽ đưa ra thông báo \_doing\_it\_wrong.

Định nghĩa tuyến API REST cho myplugin / v1 / author thiếu đối số allow\_callback bắt buộc. Đối với các tuyến API REST được thiết kế để công khai, hãy sử dụng \_\_return\_true làm lệnh gọi lại quyền.

Nếu điểm cuối API REST của bạn là công khai, bạn có thể sử dụng \_\_return\_true làm lệnh gọi lại quyền.

```
<?php
add_action('rest_api_init', function () {
  register_rest_route('myplugin/v1', '/author/(?P<id>\d+)', array(
    'methods'             => 'GET',
    'callback'            => 'my_awesome_func',
    'permission_callback' => '__return_true',
  ));
});
?>
```

#### Discovery <a href="#discovery" id="discovery"></a>

Nếu bạn muốn bật Khám phá tài nguyên cho điểm cuối tùy chỉnh của mình, bạn có thể làm như vậy bằng cách sử dụng bộ lọc rest\_queried\_resource\_route. Ví dụ: hãy xem xét một truy vấn tùy chỉnh var my-route chứa id của tài nguyên tùy chỉnh của bạn. Đoạn mã sau sẽ thêm liên kết khám phá bất cứ khi nào var truy vấn tuyến đường của tôi được sử dụng.

```
<?php
function my_plugin_rest_queried_resource_route($route) {
  $id = get_query_var('my-route');
  if (!$route && $id) {
    $route = '/my-ns/v1/items/' . $id;
  }
  return $route;
}
add_filter('rest_queried_resource_route', 'my_plugin_rest_queried_resource_route');
?>
```

Lưu ý: Nếu điểm cuối của bạn đang mô tả loại bài đăng tùy chỉnh hoặc phân loại tùy chỉnh, bạn rất có thể sẽ muốn sử dụng bộ lọc rest\_route\_for\_post hoặc rest\_route\_for\_term để thay thế.

### The Controller Pattern  <a href="#the-controller-pattern" id="the-controller-pattern"></a>

Mẫu bộ điều khiển là phương pháp hay nhất để làm việc với các điểm cuối phức tạp với API.

Bạn nên đọc “Mở rộng lớp học nội bộ” trước khi đọc phần này. Làm như vậy sẽ giúp bạn quen với các mẫu được sử dụng bởi các tuyến mặc định, đây là cách tốt nhất. Mặc dù không bắt buộc lớp bạn sử dụng để xử lý yêu cầu của mình phải mở rộng lớp WP\_REST\_Controller hoặc một lớp mở rộng nó, nhưng làm như vậy cho phép bạn kế thừa công việc đã thực hiện trong các lớp đó. Ngoài ra, bạn có thể yên tâm rằng bạn đang làm theo các phương pháp hay nhất dựa trên các phương pháp kiểm soát mà bạn đang sử dụng.

Về cốt lõi của chúng, bộ điều khiển không gì khác hơn là một tập hợp các phương thức thường được đặt tên để phù hợp với các quy ước REST, cùng với một số trình trợ giúp hữu ích. Bộ điều khiển đăng ký các tuyến đường của họ trong phương thức register\_routes, trả lời các yêu cầu bằng get\_items, get\_item, create\_item, update\_item và delete\_item, và có các phương pháp kiểm tra quyền được đặt tên tương tự. Làm theo mẫu này sẽ đảm bảo bạn không bỏ lỡ bất kỳ bước hoặc chức năng nào trong điểm cuối của mình.

Để sử dụng bộ điều khiển, trước tiên bạn cần phân lớp bộ điều khiển cơ sở. Điều này cung cấp cho bạn một tập hợp các phương pháp cơ bản, sẵn sàng để bạn thêm hành vi của riêng mình vào.

Khi chúng ta đã phân lớp bộ điều khiển, chúng ta cần khởi tạo lớp để nó hoạt động. Điều này nên được thực hiện bên trong một lệnh gọi lại được nối vào rest\_api\_init, điều này đảm bảo chúng ta chỉ khởi tạo lớp khi chúng ta cần. Mẫu điều khiển bình thường là gọi $ controller-> register\_routes () bên trong lệnh gọi lại này, nơi lớp sau đó có thể đăng ký các điểm cuối của nó.

The following is a “starter” custom route:
