Bỏ qua menu, tới nội dung
Thành viên The MONA Group
Thành viên The MONA Group
Sản phẩm và viết theo yêu cầu
1900 636 648Tư vấn miễn phí, 8h–22h
MONA OS 2.0Hệ thống quản trị MONA tự phát triển, nối 7 phần mềm nội bộ về một dữ liệu, có Gấu Quản Trị trả lời câu hỏi điều hành.7 phần mềm1 trục dữ liệu8 AI AgentXem MONA OS hoạt động
Dự án giáo dụcThe IELTS WorkshopPhần mềm quản lý chuỗi 11 cơ sở luyện thi, kèm app cho học viên20238 tháng12 ngườiXem hồ sơ dự án Xem thêm dự án Khoa Y
Dự án bán lẻHình minh hoạ gấu MONA bán trang sức tại quầy kính, cạnh màn hình bán hàng và tồn khoNgọc Thành JewelryPhần mềm quản lý chuỗi cửa hàng trang sức, tích hợp xuất hoá đơn20246 tháng7 ngườiXem hồ sơ dự án
Dự án sản xuấtHình minh hoạ gấu MONA hướng dẫn công nhân học bài trên phần mềm đào tạo trong phòng họp nhà máyPolytex Far Eastern Việt NamPhần mềm đào tạo công nhân viên chạy trong mạng nội bộ nhà máy20234 tháng8 ngườiXem hồ sơ dự án
Dự án nhân sựHình minh hoạ gấu MONA đứng lớp đào tạo cho bác sĩ, điều dưỡng bằng phần mềm học trực tuyếnBệnh viện Hoàn Mỹ Sài GònViệc đào tạo nhân sự chuyển từ Excel sang phần mềm MONA viết riêng20247 tuần13 moduleXem hồ sơ dự án
Sản phẩm có sẵnHình minh hoạ gấu MONA phục vụ bàn, khách quét mã QR trên bàn để gọi mónnhahang.aiGọi món tại bàn bằng mã QR, kết nối bếp, quản lý bàn, định lượng nguyên liệuNhà hàngQuán ănChuỗi ăn uốngXem nhahang.ai
Sản phẩm có sẵnMONA HouseTự lập hoá đơn tiền phòng, gửi mã QR qua Zalo, báo có khi khách chuyển khoảnNhà trọCăn hộ cho thuêXem MONA House
Sản phẩm có sẵnMONA NHTQĐặt hàng Taobao, 1688, Tmall, ví khách hàng và theo dõi vận đơn cho công ty nhập hàngTaobao1688TmallXem MONA NHTQ
Tư vấn miễn phí, 8h–22h mỗi ngày
Kiến thức phần mềm

Đưa custom post type và trường tùy chỉnh ra REST API bằng show_in_rest

MONA Software biên soạnCập nhật · Đăng · 11 phút đọc

Đưa custom post type và trường tùy chỉnh ra REST API bằng show_in_rest

Custom post type (CPT) là kiểu nội dung do đội kỹ thuật tự tạo, ví dụ dự án, sản phẩm hay nhân sự. Mặc định, CPT không xuất hiện trên REST API của WordPress, dù nó có thể đã hiện đầy đủ trong màn hình quản trị. Muốn ứng dụng bên ngoài đọc hoặc ghi được, phải khai báo show_in_rest cho CPT, và làm tương tự cho taxonomy cùng từng trường meta cần lộ ra.

Nếu chưa rõ WordPress là gì và khi nào site đủ dùng, xem WordPress là gì, khi nào đủ dùng. Bài này đi lần lượt qua ba chỗ cần khai báo, đưa một đoạn PHP tối thiểu đặt trong plugin, rồi chỉ cách kiểm bằng một lệnh GET. Tên tham số, giá trị mặc định và phiên bản đều lấy từ trang tham chiếu của WordPress và tài liệu của ACF, tra ngày 13/10/2026. Trình tự trong bài đi từ CPT xuống taxonomy rồi đến meta, mỗi tầng có một lần kiểm riêng, để khi lỗi xảy ra thì biết nó nằm ở tầng nào. Nếu đội kỹ thuật đang dựng website WordPress làm nguồn nội dung cho một giao diện riêng, bước này thường là việc đầu tiên, xem thêm headless WordPress khác WordPress thường ở đâu.

Khai báo show_in_rest khi đăng ký CPT

Hàm register_post_type() phải được gọi trên hook init. Trang tham chiếu khuyên đừng gắn đăng ký post type trước hook này. Tham số show_in_rest có mặc định là false, vì vậy một CPT đăng ký đủ mà không khai báo vẫn kín với REST, dù nó đã hiện đầy đủ trong trang quản trị. Trang changelog ghi tham số này có từ WordPress 4.7.0, nghĩa là với bản từ 4.7.0 trở lên, khai báo này có sẵn trong lõi và không cần cài thêm plugin.

Bảng dưới liệt kê bốn tham số liên quan tới REST, đúng theo mô tả trên trang tham chiếu.

Tham số Ý nghĩa Mặc định
show_in_rest Cho phép CPT xuất hiện trên REST API, tạo route trong namespace. Bật true thì trình soạn khối Gutenberg cũng dùng được CPT. false
rest_base Đoạn đường dẫn của route. Ví dụ đặt du-an thì route là /wp-json/wp/v2/du-an. Tên CPT, tức $post_type
rest_namespace Namespace của route. Trang ghi tham số này có từ bản 5.9.0. wp/v2
rest_controller_class Lớp controller xử lý yêu cầu, phải kế thừa WP_REST_Controller. WP_REST_Posts_Controller

Với rest_base, nếu để mặc định thì đường dẫn trùng tên CPT. Khoá của CPT phải viết thường, không quá 20 ký tự, chỉ gồm chữ không dấu, số, dấu gạch ngang và gạch dưới, theo mô tả của trang tham chiếu. Ví dụ trong bài này dùng namespace mặc định wp/v2. Tài liệu REST API handbook lấy ví dụ CPT book đặt rest_base là books, để đường dẫn thành số nhiều. Việc đổi rest_base cần làm trước khi có ứng dụng nào gọi, vì sau khi đổi, đường dẫn cũ không còn là đường dẫn của CPT.

Trang tài liệu WordPress liệt kê tham số show_in_rest, rest_base và rest_namespace của register_post_type
Mục Parameters trên trang register_post_type() của developer.wordpress.org, chụp ngày 13/10/2026. Ảnh cho thấy show_in_rest, rest_base, rest_namespace và rest_controller_class cùng giá trị mặc định ghi ngay bên dưới.

Đưa taxonomy ra REST API bằng register_taxonomy

Taxonomy là cách phân nhóm bài, ví dụ “Loại dự án” gồm website, phần mềm và ứng dụng di động. Hàm register_taxonomy() có bộ tham số giống CPT: show_in_rest mặc định là false, rest_base mặc định là tên taxonomy, rest_controller_class mặc định là WP_REST_Terms_Controller. Hàm này cũng không được gọi trước hook init, theo ghi chú của trang tham chiếu, nên người làm thường đặt đăng ký taxonomy ngay cạnh đăng ký CPT để dễ đọc.

Trong ví dụ của handbook, taxonomy genre được gắn vào CPT book, và cả hai đều bật show_in_rest. Cặp khai báo này cần kiểm cùng lúc: gọi GET tới đường dẫn của CPT rồi tới đường dẫn của taxonomy, sau đó đối chiếu từng kết quả với trang quản trị. Nếu một trong hai đường dẫn trả lỗi, phần còn thiếu sẽ lộ ra ngay trong bước kiểm này.

Ngăn nhựa xếp chồng, mỗi ngăn giữ một loại đồ riêng
Nhiều ngăn nhỏ xếp chồng, mỗi ngăn giữ một loại đồ, cùng ý với taxonomy gom bài vào từng nhóm. Ảnh: pasukaru76, CC0 1.0, lấy từ Openverse, nguồn https://www.flickr.com/photos/38451115@N04/14666197028.

Đưa trường meta ra REST API bằng register_post_meta

Trường tùy chỉnh được lưu dưới dạng meta. Trang register_post_meta() ghi rằng hàm này nhận cùng tham số với register_meta(), và hàm được thêm từ bản 4.9.8. Ba điều cần nhớ khi lộ meta ra REST: show_in_rest mặc định là false, CPT phải khai báo hỗ trợ custom-fields, và auth_callback quyết định ai được ghi.

Tham số Ý nghĩa Mặc định
type Kiểu dữ liệu: string, boolean, integer, number, array hoặc object. Trang không ghi trong bảng tham số
single Một giá trị hay một mảng giá trị cho mỗi bài. false (theo ví dụ trên trang)
show_in_rest Cho phép giá trị lộ trong phản hồi REST, ở khoá meta. Với kiểu mảng phải khai báo schema. false
auth_callback Hàm được gọi khi kiểm tra quyền edit_post_meta, add_post_meta và delete_post_meta. null, khi đó WordPress dùng is_protected_meta()
sanitize_callback Hàm làm sạch giá trị trước khi lưu. Trang không ghi trong bảng tham số

Với kiểu array, show_in_rest không thể chỉ là true, vì trang register_meta() yêu cầu khai báo schema cho từng phần tử của mảng. Thiếu schema, WordPress ghi nhận lỗi dùng sai hàm và trường không được đăng ký đúng cách. Các kiểu đơn giản như string, integer hay boolean chỉ cần true. Trang tham chiếu có ví dụ riêng cho trường mảng, và đội kỹ thuật nên đọc kỹ ví dụ đó trước khi lộ một trường mảng ra ngoài.

Về quyền ghi, trang register_meta() ghi rằng auth_callback được gọi khi kiểm tra các quyền trên. Khi bỏ trống, WordPress coi khoá có dấu gạch dưới ở đầu là khoá bảo vệ và từ chối ghi, còn khoá thường thì được cho phép. Vì vậy, trường chứa dữ liệu nhạy cảm như số tiền hợp đồng hay ghi chú nội bộ cần có auth_callback riêng, do đội kỹ thuật viết và kiểm, thay vì dựa vào mặc định của WordPress. Đây là chỗ dễ sót nhất.

Trang tài liệu register_meta mô tả show_in_rest và auth_callback của trường tùy chỉnh
Danh sách tham số của register_meta() trên developer.wordpress.org, chụp ngày 13/10/2026. Ảnh cho thấy mô tả show_in_rest, điều kiện CPT phải hỗ trợ custom fields, và auth_callback.

Đoạn mã PHP tối thiểu để đặt trong plugin

Đoạn dưới đăng ký CPT project, taxonomy project_type và trường client_budget. Đặt trong một plugin riêng sẽ dễ kiểm và dễ tắt hơn là thêm vào functions.php của theme. Hàm kích hoạt gọi lại các hàm đăng ký trước khi làm mới quy tắc đường dẫn, vì flush chỉ nhìn thấy những post type đã được đăng ký tại thời điểm đó. Đoạn mã dưới đây đã kiểm cú pháp PHP.

<?php
/**
 * Plugin Name: MONA demo REST cho CPT
 */

// Register the "project" custom post type and expose it in the REST API.
add_action( 'init', 'mona_demo_register_project' );

function mona_demo_register_project() {
	register_post_type(
		'project',
		array(
			'labels'       => array(
				'name'          => 'Dự án',
				'singular_name' => 'Dự án',
			),
			'public'       => true,
			'show_in_rest' => true,     // Create the route, default is false.
			'rest_base'    => 'du-an',  // URL segment: /wp-json/wp/v2/du-an
			'supports'     => array( 'title', 'editor', 'custom-fields' ), // Needed for meta in REST.
		)
	);
}

// Register the "project_type" taxonomy and expose its terms in the REST API.
add_action( 'init', 'mona_demo_register_project_type', 30 );

function mona_demo_register_project_type() {
	register_taxonomy(
		'project_type',
		array( 'project' ),
		array(
			'label'        => 'Loại dự án',
			'hierarchical' => true,
			'show_in_rest' => true,          // Create the terms route.
			'rest_base'    => 'loai-du-an',
		)
	);
}

// Register the "client_budget" meta field and expose it in REST responses.
add_action( 'init', 'mona_demo_register_meta' );

function mona_demo_register_meta() {
	register_post_meta(
		'project',
		'client_budget',
		array(
			'type'          => 'integer',
			'single'        => true,
			'show_in_rest'  => true,     // Value appears under the "meta" key.
			// Decide who may write the value. Here: users who can edit the post.
			'auth_callback' => function ( $allowed, $meta_key, $post_id ) {
				return current_user_can( 'edit_post', $post_id );
			},
		)
	);
}

// Flush rewrite rules when the plugin is activated, so the new routes work.
register_activation_hook( __FILE__, 'mona_demo_activate' );

function mona_demo_activate() {
	mona_demo_register_project();
	mona_demo_register_project_type();
	flush_rewrite_rules();
}

// Flush again on deactivation, so the old rules are removed.
register_deactivation_hook( __FILE__, 'flush_rewrite_rules' );

Tài liệu REST API handbook cũng có ví dụ tối thiểu tương tự, đăng ký CPT book với show_in_rest bật true.

Đoạn mã mẫu trong tài liệu WordPress đăng ký post type với show_in_rest true
Đoạn mã mẫu trong REST API handbook, mục đăng ký CPT có hỗ trợ REST, chụp ngày 13/10/2026. Ảnh cho thấy cặp public và show_in_rest => true trong mảng tham số.

Thứ tự làm để gọi được API

  1. Chọn slug CPT và rest_base trước khi đăng ký. Đổi sau khi đã có ứng dụng gọi sẽ phải sửa lại mọi nơi trỏ tới đường dẫn cũ.
  2. Thêm show_in_rest vào register_post_type() trước, vì đó là bước tạo route cho CPT. Sau đó mới thêm show_in_rest và rest_base cho taxonomy đi kèm, để mỗi bước kiểm được riêng.
  3. Nếu cần lộ meta, khai báo show_in_rest trong register_post_meta() và thêm custom-fields vào danh sách hỗ trợ của CPT.
  4. Kích hoạt plugin. Nếu đã kích hoạt từ trước, vào Cài đặt, mục Đường dẫn tĩnh, rồi bấm Lưu để làm mới quy tắc.
  5. Gọi GET tới đường dẫn REST và đối chiếu kết quả với dữ liệu trong trang quản trị.

Các bước trên làm được cả trên máy thử trước khi lên máy thật. Trên máy thử, chỉ cần một bản WordPress cài sẵn và thư mục plugin chứa file đã viết ở trên. Sau đó làm đúng thứ tự, đừng nhảy sang bước kiểm khi chưa làm mới quy tắc đường dẫn. Ghi lại kết quả của từng bước giúp khoanh vùng lỗi nhanh hơn khi có ứng dụng khác bắt đầu gọi vào. Kiểm xong mới đi tiếp.

Kiểm bằng GET trên đường dẫn REST

Lệnh dưới lấy năm dự án mới nhất. Thay example.com bằng domain thật của website.

curl -s "https://example.com/wp-json/wp/v2/du-an?per_page=5"

Kết quả là một mảng JSON, mỗi bài có id, title và slug. Nếu sau khi sửa bài mà trang hiển thị chưa đổi, xem sửa bài trên WordPress bao lâu thì trang đổi. Tham số per_page giới hạn số bài mỗi trang, nên khi thử với một CPT lớn, đội kỹ thuật nên đặt số nhỏ trước rồi mới tăng dần. Giá trị của trường đã khai báo show_in_rest nằm trong khoá meta của từng bài. Nếu thiếu khoá meta, hoặc khoá có nhưng không có client_budget, kiểm lại hai điều kiện: show_in_rest của trường có bật không, và CPT có hỗ trợ custom-fields không.

Khi cần kiểm riêng một bài, thêm id vào cuối đường dẫn, ví dụ /wp-json/wp/v2/du-an/123. Cách này cho kết quả của đúng bài đó, dễ đối chiếu với màn hình quản trị hơn là đọc cả danh sách. Thao tác POST cần xác thực, theo ghi chú trong tài liệu ACF, vì vậy lệnh GET ở đây chỉ dùng để kiểm đọc, không dùng để ghi.

Ba lỗi hay gặp khi đưa CPT ra REST API

  • Đổi slug hoặc rest_base mà không làm mới quy tắc đường dẫn. Trang tham chiếu khuyến nghị gọi flush_rewrite_rules() trong hook kích hoạt và hủy kích hoạt khi đăng ký post type trong plugin. Nếu không làm, phải vào Cài đặt, mục Đường dẫn tĩnh và làm mới thủ công trước khi kiểm bất kỳ đường dẫn REST nào, vì nếu không sẽ khó biết lỗi đến từ khai báo hay từ quy tắc đường dẫn cũ.
  • Meta không lộ dù đã đăng ký. Nguyên nhân thường là show_in_rest của trường vẫn là false, hoặc CPT không hỗ trợ custom-fields. Trang register_meta() nêu cả hai điều kiện.
  • Ghi meta bị từ chối. Thường do khoá có dấu gạch dưới ở đầu, vì khoá đó bị coi là bảo vệ khi không có auth_callback, hoặc do auth_callback trả về false với tài khoản đang gọi. Kiểm lại auth_callback và quyền của tài khoản trước khi sửa phần còn lại.

Trường tùy chỉnh từ plugin như ACF khai báo thế nào

ACF là plugin tạo trường tùy chỉnh phổ biến trên WordPress. Theo tài liệu REST API chính thức của ACF, nhóm trường mặc định không hiện trên REST API. Phải bật “Show in REST API” trong mục Group Settings của từng nhóm trường, vì tài liệu ghi việc bật này thực hiện cho từng nhóm chứ không cho cả site một lần. Với CPT tạo trong ACF, mục REST API trong phần Advanced Configuration cho chỉnh khả năng hiện, namespace và lớp controller.

Dữ liệu trường ACF trả về trong một đối tượng acf của phản hồi GET. Đây là khác biệt cần nhớ khi đọc JSON: trường ACF nằm trong acf, còn meta đăng ký bằng register_meta() nằm trong meta, nên hai khoá này không thay thế được cho nhau. Trường đăng ký bằng code dùng register_post_meta(), còn trường tạo trong giao diện ACF dùng cài đặt của ACF. Chọn một cách cho mỗi trường để dễ bảo trì. Với filter acf/settings/rest_api_enabled trả về false, ACF tắt hẳn phần REST của mình, và mọi cài đặt Show in REST API trên từng nhóm trường sẽ không còn tác dụng.

Hỏi đáp

CPT đã đăng ký nhưng không có trên REST API, nguyên nhân thường là gì?

Thường là thiếu show_in_rest trong tham số của register_post_type(), vì mặc định là false. Cũng cần kiểm lại hàm đăng ký có chạy trên hook init hay không. Nếu cả hai điều đó đều đúng, bước tiếp theo là làm mới quy tắc đường dẫn theo đúng thứ tự đã nêu, rồi gọi lại đường dẫn REST bằng lệnh GET ở phần kiểm để xem kết quả có đổi không.

show_in_rest của CPT khác show_in_rest của meta thế nào?

Với CPT và taxonomy, show_in_rest tạo route để đọc và ghi bài hoặc term trong namespace đã chọn, còn rest_base quyết định đường dẫn cụ thể của route đó. Với meta, show_in_rest không tạo route riêng mà đưa giá trị vào khoá meta của phản hồi bài viết, nên giá trị đó đi cùng với bài khi bài được đọc qua REST. Hai tham số có cùng tên nhưng tác dụng khác nhau.

Meta có bắt buộc phải có custom-fields trong CPT không?

Có. Trang register_meta() ghi rằng CPT phải khai báo hỗ trợ custom fields thì meta đã đăng ký mới truy cập được qua REST.

Bỏ trống auth_callback có an toàn không?

Phụ thuộc vào loại dữ liệu. Khoá có dấu gạch dưới ở đầu được coi là bảo vệ, còn khoá thường được cho phép ghi. Trường chứa thông tin nội bộ cần có auth_callback riêng, trả về kết quả theo quyền của người đang sửa bài.

Đổi rest_base sau khi ứng dụng đã gọi API thì xử lý thế nào?

Đường dẫn cũ không còn là đường dẫn của CPT sau khi đổi, vì vậy ứng dụng phải cập nhật lại. Nếu website đã có lưu lượng và cần giữ đường dẫn cho SEO, xem thêm cách chuyển WordPress sang headless mà vẫn giữ link và SEO.

Khi nội dung WordPress cần ra một giao diện riêng, phần việc thường gồm cả ba lớp này cùng lúc: CPT, taxonomy và trường meta, cộng thêm quyền ghi. Phần việc đó nằm trong dịch vụ lập trình website headless WordPress của MONA. Để trao đổi phạm vi và thời gian làm, gọi hotline 1900 636 648.

Đọc thêm

Đội MONA gặp khách hàng để khảo sát quy trình trước khi làm phần mềm

Kiến thức phần mềm

Gửi MONA quy trình đang chạy để nhận hướng làm phần mềm

Đội MONA Software khảo sát nghiệp vụ, thiết kế cơ sở dữ liệu, lập trình, bàn giao và đi cùng qua giai đoạn vận hành thử.