WordPress REST API คือชุด HTTP Interface ที่ช่วยให้แอปพลิเคชันภายนอก ไม่ว่าจะเป็น JavaScript, Mobile App, หรือบริการ Third-Party สามารถอ่าน เขียน และจัดการข้อมูลบน WordPress ได้โดยตรงผ่านโปรโตคอล HTTP โดยส่งและรับข้อมูลในรูปแบบ JSON เปิดตัวอย่างเป็นทางการใน WordPress 4.7 และปัจจุบันกลายเป็นหัวใจสำคัญของสถาปัตยกรรม Headless WordPress และ Single-Page Application ที่ใช้ WordPress เป็น Backend
บทความนี้จะพาคุณทำความเข้าใจ WordPress REST API ตั้งแต่แนวคิดพื้นฐาน ไปจนถึงการใช้งาน Endpoint จริง การเรียก API ด้วย JavaScript และ PHP และการสร้าง Custom Route ของตัวเอง รวมถึงแนวทางรักษาความปลอดภัยที่ควรรู้ก่อน deploy ขึ้น Production
WordPress REST API คืออะไร และทำงานอย่างไร
REST (Representational State Transfer) เป็น architectural style สำหรับ Web API ที่ใช้ HTTP Verbs มาตรฐาน ได้แก่ GET, POST, PUT, PATCH และ DELETE ในการสื่อสาร WordPress ได้นำแนวคิดนี้มาสร้าง Interface ที่เปิดให้เข้าถึงข้อมูลทุกประเภทของเว็บไซต์ เช่น Posts, Pages, Users, Media, Categories, Tags และ Custom Post Types
เมื่อส่ง HTTP Request ไปยัง WordPress API Endpoint Server จะตรวจสอบสิทธิ์ ประมวลผล และส่งข้อมูลกลับมาในรูปแบบ JSON ผ่าน Route ที่ขึ้นต้นด้วย /wp-json/ เสมอ ตัวอย่างเช่น:
- GET
/wp-json/wp/v2/posts— ดึงรายการบทความทั้งหมด - GET
/wp-json/wp/v2/posts/123— ดึงบทความ ID 123 - POST
/wp-json/wp/v2/posts— สร้างบทความใหม่ (ต้อง Authenticate) - PUT
/wp-json/wp/v2/posts/123— แก้ไขบทความ ID 123 (ต้อง Authenticate) - DELETE
/wp-json/wp/v2/posts/123— ลบบทความ ID 123 (ต้อง Authenticate)
จุดแข็งของ REST API คือการแยก Frontend ออกจาก Backend โดยสิ้นเชิง คุณสามารถใช้ React, Vue, Next.js หรือ Flutter เป็น Frontend และให้ WordPress ทำหน้าที่เพียงเก็บข้อมูลและจัดการ Content ผ่าน API เท่านั้น รูปแบบนี้เรียกว่า Headless WordPress
Endpoint มาตรฐานที่ควรรู้จัก
WordPress REST API มี Namespace หลักคือ wp/v2 ซึ่งรวม Endpoint สำหรับข้อมูลพื้นฐานทั้งหมด ตารางด้านล่างสรุป Endpoint ที่ใช้บ่อยที่สุด:
| Endpoint | Method | คำอธิบาย | Auth |
|---|---|---|---|
/wp/v2/posts |
GET | ดึงรายการบทความ (Public) | ไม่จำเป็น |
/wp/v2/posts |
POST | สร้างบทความใหม่ | จำเป็น |
/wp/v2/pages |
GET | ดึงรายการหน้า (Public) | ไม่จำเป็น |
/wp/v2/users |
GET | ดึงรายการผู้ใช้ | จำเป็น (บางส่วน) |
/wp/v2/media |
GET / POST | ดึง/อัปโหลด Media | POST จำเป็น |
/wp/v2/categories |
GET | ดึงรายการหมวดหมู่ | ไม่จำเป็น |
/wp/v2/tags |
GET | ดึงรายการ Tag | ไม่จำเป็น |
/wp/v2/comments |
GET / POST | ดึง/สร้าง Comment | POST อาจจำเป็น |
คุณสามารถดู Endpoint ทั้งหมดที่ติดตั้งอยู่บนเว็บไซต์ของคุณได้โดยเข้า https://yoursite.com/wp-json/ ซึ่งจะแสดง Discovery Document ในรูปแบบ JSON รายการ routes และ namespaces ทั้งหมด
เรียก API ด้วย JavaScript (Fetch API)
การดึงข้อมูลจาก WordPress REST API ด้วย JavaScript ทำได้ง่ายมากผ่าน Fetch API หรือ Axios โค้ดด้านล่างแสดงตัวอย่างการดึงบทความ 5 รายการล่าสุดและแสดงผลบนหน้าเว็บ:
// ดึงบทความ 5 รายการล่าสุด
async function getLatestPosts() {
const response = await fetch(
'https://yoursite.com/wp-json/wp/v2/posts?per_page=5&_fields=id,title,link,excerpt'
);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const posts = await response.json();
posts.forEach(post => {
console.log(post.id, post.title.rendered, post.link);
});
}
getLatestPosts();
สังเกตว่าใช้ parameter _fields เพื่อเลือกเฉพาะ field ที่ต้องการ ซึ่งช่วยลดขนาดข้อมูลที่ถ่ายโอนได้มากเมื่อเทียบกับการดึง full object ที่มี field กว่า 30+ ตัว
Query Parameters ที่ใช้บ่อย
REST API มี parameters มาตรฐานสำหรับกรองและเรียงข้อมูล ตัวที่ใช้บ่อยได้แก่:
per_page— จำนวนรายการต่อหน้า (1-100, default 10)page— หมายเลขหน้า สำหรับ Paginationsearch— ค้นหาด้วย keywordcategories— กรองตาม category ID (คั่นด้วย comma)tags— กรองตาม tag IDorderby— เรียงตาม field เช่น date, title, modifiedorder— ทิศทาง asc หรือ desc_fields— เลือกเฉพาะ field ที่ต้องการ (ประหยัด bandwidth)status— กรองตามสถานะ publish, draft, private
// กรองบทความตาม category และเรียงตามชื่อ
const url = new URL('https://yoursite.com/wp-json/wp/v2/posts');
url.searchParams.set('categories', '5,8');
url.searchParams.set('per_page', '10');
url.searchParams.set('orderby', 'title');
url.searchParams.set('order', 'asc');
url.searchParams.set('_fields', 'id,title,link,date');
const res = await fetch(url.toString());
const data = await res.json();
Authentication ด้วย Application Password
สำหรับ Endpoint ที่ต้องการสิทธิ์ เช่น การสร้าง แก้ไข หรือลบข้อมูล คุณต้องส่ง Credentials ไปพร้อมกับ Request WordPress รองรับหลายวิธี แต่วิธีที่แนะนำสำหรับการใช้งานทั่วไปคือ Application Password ซึ่งเพิ่มมาใน WordPress 5.6
ขั้นตอนสร้าง Application Password
- เข้าไปที่ WordPress Admin > Users > Your Profile
- เลื่อนลงไปที่ส่วน "Application Passwords"
- ใส่ชื่อแอปพลิเคชัน เช่น "My App" แล้วกด "Add New Application Password"
- WordPress จะสร้าง Password ให้ครั้งเดียว (ไม่แสดงซ้ำ) ให้บันทึกเก็บไว้
// ส่ง Request พร้อม Basic Auth (Application Password)
const username = 'your_username';
const appPassword = 'xxxx xxxx xxxx xxxx xxxx xxxx'; // ตัดช่องว่างออกก็ได้
const credentials = btoa(`${username}:${appPassword}`);
const response = await fetch('https://yoursite.com/wp-json/wp/v2/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Basic ${credentials}`
},
body: JSON.stringify({
title: 'บทความทดสอบจาก API',
content: 'เนื้อหาบทความ...',
status: 'draft'
})
});
const newPost = await response.json();
console.log('สร้างบทความ ID:', newPost.id);
เคล็ดลับด้านความปลอดภัย: ไม่ควรเก็บ Application Password ไว้ใน Frontend JavaScript โดยตรง เพราะผู้ใช้สามารถดูได้จาก Source Code หรือ DevTools แนะนำให้เก็บ Credentials ในฝั่ง Server และให้ Frontend ส่ง Request ผ่าน Backend Proxy แทน นอกจากนี้ควรสร้าง Application Password แยกสำหรับแต่ละแอป และ Revoke ทันทีเมื่อไม่ใช้แล้ว
เรียก API ด้วย PHP (wp_remote_get)
สำหรับผู้ที่ต้องการเรียก WordPress REST API จาก PHP ไม่ว่าจะเป็นจาก Plugin อื่น หรือเว็บไซต์ภายนอก WordPress มี HTTP API functions ในตัวที่ใช้งานได้ง่าย หรือจะใช้ cURL โดยตรงก็ได้:
<?php
// วิธีที่ 1: ใช้ WordPress HTTP API (ถ้าอยู่ในระบบ WP)
$response = wp_remote_get(
'https://yoursite.com/wp-json/wp/v2/posts?per_page=5',
array(
'timeout' => 15,
'headers' => array(
'Accept' => 'application/json',
)
)
);
if ( is_wp_error( $response ) ) {
error_log( 'API Error: ' . $response->get_error_message() );
return false;
}
$body = wp_remote_retrieve_body( $response );
$posts = json_decode( $body, true );
foreach ( $posts as $post ) {
echo $post['id'] . ': ' . $post['title']['rendered'] . "\n";
}
// วิธีที่ 2: ใช้ cURL (สำหรับ PHP ทั่วไป)
$ch = curl_init('https://yoursite.com/wp-json/wp/v2/posts?per_page=5');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Accept: application/json']);
curl_setopt($ch, CURLOPT_USERAGENT, 'MyApp/1.0');
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
$result = curl_exec($ch);
curl_close($ch);
$posts = json_decode($result, true);
?>
สร้าง Custom REST Route ใน Plugin หรือ functions.php
ความสามารถที่ทรงพลังที่สุดของ WordPress REST API คือการสร้าง Custom Route ได้เอง ซึ่งเหมาะสำหรับกรณีที่ต้องการ endpoint สำหรับข้อมูลเฉพาะของเว็บไซต์ เช่น สรุปยอดขาย, ดึงข้อมูล Custom Post Type พร้อมตัวกรองพิเศษ หรือส่งผลลัพธ์จากการคำนวณ
<?php
// ลงทะเบียน Custom Route ใน functions.php หรือ Plugin
add_action( 'rest_api_init', function() {
register_rest_route(
'myplugin/v1', // namespace
'/summary', // path
array(
'methods' => 'GET',
'callback' => 'myplugin_get_summary',
'permission_callback' => '__return_true', // public
)
);
// Route สำหรับ POST ที่ต้อง Authenticate
register_rest_route(
'myplugin/v1',
'/data',
array(
'methods' => 'POST',
'callback' => 'myplugin_save_data',
'permission_callback' => function() {
return current_user_can( 'edit_posts' );
},
'args' => array(
'title' => array(
'required' => true,
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
),
'amount' => array(
'required' => true,
'type' => 'number',
),
),
)
);
} );
// Callback function สำหรับ GET
function myplugin_get_summary( WP_REST_Request $request ) {
$data = array(
'total_posts' => wp_count_posts()->publish,
'total_pages' => wp_count_posts('page')->publish,
'total_users' => count_users()['total_users'],
'site_name' => get_bloginfo('name'),
'generated_at' => current_time('mysql'),
);
return rest_ensure_response( $data );
}
// Callback function สำหรับ POST
function myplugin_save_data( WP_REST_Request $request ) {
$title = $request->get_param('title');
$amount = $request->get_param('amount');
// ประมวลผลและบันทึกข้อมูล...
return new WP_REST_Response(
array( 'success' => true, 'message' => 'บันทึกสำเร็จ' ),
201
);
}
?>
หลังเพิ่มโค้ดนี้ คุณสามารถเรียก https://yoursite.com/wp-json/myplugin/v1/summary เพื่อดูข้อมูลสรุปได้ทันที ตรวจสอบว่า Permalink ของ WordPress ไม่ได้ตั้งค่าเป็น "Plain" เพราะจะทำให้ /wp-json/ ไม่ทำงาน
การ Filter และ Extend ข้อมูลที่ส่งออก
บางครั้งคุณต้องการเพิ่มข้อมูลพิเศษเข้าไปใน Response ของ Endpoint มาตรฐาน เช่น ต้องการให้ /wp/v2/posts ส่ง Custom Field บางตัวมาด้วย ทำได้โดยใช้ register_rest_field:
<?php
// เพิ่ม Custom Field "featured_image_url" เข้าไปใน posts endpoint
add_action( 'rest_api_init', function() {
register_rest_field(
'post', // post type
'featured_image_url', // ชื่อ field ใหม่
array(
'get_callback' => function( $post_arr ) {
$thumb_id = get_post_thumbnail_id( $post_arr['id'] );
if ( ! $thumb_id ) return null;
$img = wp_get_attachment_image_src( $thumb_id, 'medium' );
return $img ? $img[0] : null;
},
'schema' => array(
'description' => 'URL รูป Featured Image ขนาด medium',
'type' => 'string',
'format' => 'uri',
),
)
);
} );
?>
หลังเพิ่มโค้ดนี้ ทุก Response ของ /wp/v2/posts จะมี field featured_image_url เพิ่มเข้ามา ทำให้ Frontend ไม่ต้องส่ง Request เพิ่มเพื่อดึงรูปภาพ
การรักษาความปลอดภัยของ WordPress REST API
WordPress REST API เปิด Public Endpoint บางส่วนโดย Default ซึ่งอาจเป็นความเสี่ยงด้านความปลอดภัยหากไม่ได้จัดการให้ดี ประเด็นที่ควรระวังและวิธีแก้ไข:
1. Endpoint /wp/v2/users เปิดเผย Username
โดย Default Endpoint /wp-json/wp/v2/users เปิดให้ดึงรายชื่อผู้ใช้ได้ ซึ่งเป็นข้อมูลที่ผู้ไม่ประสงค์ดีอาจนำไป Brute Force ได้ แก้ได้ใน functions.php:
<?php
// ซ่อน Users Endpoint สำหรับผู้ที่ไม่มีสิทธิ์
add_filter( 'rest_endpoints', function( $endpoints ) {
if ( ! is_user_logged_in() ) {
if ( isset( $endpoints['/wp/v2/users'] ) ) {
unset( $endpoints['/wp/v2/users'] );
}
if ( isset( $endpoints['/wp/v2/users/(?P<id>[\d]+)'] ) ) {
unset( $endpoints['/wp/v2/users/(?P<id>[\d]+)'] );
}
}
return $endpoints;
} );
?>
2. จำกัด REST API เฉพาะผู้ที่ Login แล้ว
ถ้าเว็บไซต์ไม่ต้องการให้ Public เข้าถึง API เลย สามารถปิดทั้งหมดสำหรับผู้ที่ยังไม่ได้ Login:
<?php
add_filter( 'rest_authentication_errors', function( $result ) {
if ( true === $result || is_wp_error( $result ) ) {
return $result;
}
if ( ! is_user_logged_in() ) {
return new WP_Error(
'rest_not_logged_in',
'คุณต้องเข้าสู่ระบบก่อนใช้งาน REST API',
array( 'status' => 401 )
);
}
return $result;
} );
?>
3. Rate Limiting และการป้องกัน Abuse
สำหรับ API ที่เปิด Public ควรเพิ่ม Rate Limiting ผ่าน Plugin เช่น WP REST API Cache หรือตั้งค่า Cloudflare Rate Limiting Rules เพื่อจำกัดจำนวน Request ต่อ IP ต่อนาที และควร log ความผิดปกติในการเรียก API เป็นประจำ
ตัวอย่างการใช้งานจริง: Headless WordPress กับ React
ตัวอย่างต่อไปนี้แสดงโครงสร้างพื้นฐานของ React Component ที่ดึงบทความจาก WordPress REST API และแสดงผลเป็นรายการ:
// BlogList.jsx — React Component
import { useState, useEffect } from 'react';
const WP_API = 'https://yoursite.com/wp-json/wp/v2';
export default function BlogList() {
const [posts, setPosts] = useState([]);
const [loading, setLoading] = useState(true);
const [page, setPage] = useState(1);
const [total, setTotal] = useState(0);
useEffect(() => {
async function fetchPosts() {
setLoading(true);
const res = await fetch(
`${WP_API}/posts?per_page=10&page=${page}&_fields=id,title,slug,excerpt,date`
);
const totalPages = parseInt(res.headers.get('X-WP-TotalPages'), 10);
const data = await res.json();
setPosts(data);
setTotal(totalPages);
setLoading(false);
}
fetchPosts();
}, [page]);
if (loading) return <p>กำลังโหลด...</p>;
return (
<div>
{posts.map(post => (
<article key={post.id}>
<h2 dangerouslySetInnerHTML={{ __html: post.title.rendered }} />
<p dangerouslySetInnerHTML={{ __html: post.excerpt.rendered }} />
<a href={`/blog/${post.slug}`}>อ่านต่อ →</a>
</article>
))}
<button onClick={() => setPage(p => Math.max(1, p-1))} disabled={page===1}>
ย้อนกลับ
</button>
<button onClick={() => setPage(p => p+1)} disabled={page===total}>
ถัดไป
</button>
</div>
);
}
สังเกตว่า WordPress ส่ง Pagination Headers กลับมาด้วย ได้แก่ X-WP-Total (จำนวนทั้งหมด) และ X-WP-TotalPages (จำนวนหน้าทั้งหมด) ซึ่งใช้สร้าง UI Pagination ได้โดยไม่ต้องคำนวณเอง
คำถามที่พบบ่อย (FAQ)
WordPress REST API เปิดใช้งานอยู่แล้วโดยอัตโนมัติหรือไม่
ใช่ WordPress REST API เปิดใช้งานโดย Default ตั้งแต่ WordPress 4.7 เป็นต้นมา ไม่ต้องติดตั้ง Plugin เพิ่มเติม สามารถทดสอบได้ทันทีโดยเข้า URL https://yoursite.com/wp-json/wp/v2/posts ในเบราว์เซอร์ ถ้าเห็น JSON Array ของบทความแสดงว่า API พร้อมใช้งานแล้ว หากไม่เห็น ให้ตรวจสอบว่า Permalink ตั้งค่าเป็นอะไรอยู่ (Settings > Permalinks) และอย่าใช้ "Plain"
จะป้องกัน WordPress REST API ไม่ให้คนภายนอกเข้าถึงได้อย่างไร
วิธีที่พบบ่อยคือเพิ่ม Hook ใน functions.php เพื่อตรวจสอบ Authentication ก่อนตอบสนองทุก request โดยใช้ rest_authentication_errors filter ร่วมกับ is_user_logged_in() หรือจะใช้ Application Password สำหรับ endpoints เฉพาะก็ได้ นอกจากนี้ยังสามารถปิดเฉพาะ route ที่ไม่ต้องการผ่าน rest_endpoints filter ได้อีกด้วย
ความแตกต่างระหว่าง WP_REST_Request และ WP_REST_Response คืออะไร
WP_REST_Request เป็น Object ที่เก็บข้อมูลจาก HTTP Request ที่ Client ส่งมา เช่น Parameters, Headers, Body ส่วน WP_REST_Response เป็น Object ที่เราสร้างขึ้นเพื่อส่งกลับไปหา Client โดยกำหนด Data, HTTP Status Code และ Headers ได้ ทั้งสองทำงานร่วมกันในฟังก์ชัน Callback ของ Custom Route เสมอ
WordPress REST API แตกต่างจาก GraphQL อย่างไร
REST API ใช้ HTTP Endpoint แยกตามประเภทข้อมูล เช่น /wp/v2/posts สำหรับบทความ /wp/v2/users สำหรับผู้ใช้ ข้อมูลที่ได้จะครบ field ทุกอัน ส่วน GraphQL (เช่น Plugin WPGraphQL) ใช้ Single Endpoint แต่ Client ระบุเองว่าต้องการ field ไหน ทำให้ลด Over-fetching ได้ดีกว่า สำหรับโปรเจกต์ทั่วไปและ Headless CMS เล็กๆ REST API ก็เพียงพอ แต่ถ้า Frontend ซับซ้อนและมี field ที่ต้องการหลากหลาย GraphQL จะจัดการได้ยืดหยุ่นกว่า
Hosting ที่ออปติไมซ์สำหรับ WordPress
AsiaGB Hosting รองรับ PHP 8.3 MySQL LiteSpeed Cache และ WordPress Toolkit เริ่มต้น 500 บาท/ปี
ดูแพ็กเกจ Hosting