AJAX 与 Headless
REST、Cron 与 Settings API。
REST API 与 Headless(WP + Next.js)
这一课你将能做到
- 消费 WP 内置 REST API(列表、详情、分页、_fields/_embed),并说清三种认证方式
- 用 register_rest_route 自建带 permission_callback 的自定义端点
- 用本站同款 Next.js App Router 把 WP 当 Headless CMS:SSG 静态化 + ISR 增量更新
为什么要学
传统 WP 的前台由 PHP 主题渲染;Headless 模式把前台换成 Next.js——WP 只当内容仓库和编辑后台。这正是本站 java-nav 的架构思路:编辑在后台改内容,前端用 SSG/ISR 渲染,CDN 直接回静态页,性能与安全面同时受益。
人话:把 WP 想成一个自带后台的内容数据库,/wp-json/ 就是它的查询窗口。Next.js 在构建期把窗口里的数据「烤」进静态页面,编辑一发文,ISR 到点自动重烤——内容与展示彻底解耦。
先建立图像
编辑者 → WP 后台(文章/课程CPT) → MySQL
↓
REST /wp-json/wp/v2/... ← 数据出口
↓ 服务端 fetch
Next.js (app router)
build 时: generateStaticParams → 烤出全部课程详情页(SSG)
运行时: revalidate=300 → ISR 每 5 分钟后台重验证
↓
Vercel/Node 服务 → CDN → 用户浏览器
对比传统 WP:请求每次都打到 PHP+MySQL;Headless 下绝大多数用户请求根本不碰 WP。
跟着做
步骤 1:消费内置端点
# 列表:只取需要的字段,减小载荷
curl -s "http://localhost:8080/wp-json/wp/v2/posts?per_page=3&_fields=id,title,slug,link"
# 分页信息在响应头:X-WP-Total(总数) / X-WP-TotalPages
curl -s -I "http://localhost:8080/wp-json/wp/v2/posts" | grep -i x-wp
# 详情按 slug 取
curl -s "http://localhost:8080/wp-json/wp/v2/posts?slug=hello-world&_fields=title,content"
_fields 精简返回、_embed 一次带出作者/特色图等关联——这两个参数决定前端体验。
步骤 2:自建一个聚合端点
插件中注册:
add_action( 'rest_api_init', function () {
register_rest_route( 'qrocmq/v1', '/courses', array(
'methods' => WP_REST_Server::READABLE,
'permission_callback' => '__return_true', // 公开只读;写操作必须校验能力
'args' => array(
'level' => array(
'type' => 'string',
'enum' => array( 'beginner', 'advanced' ),
'sanitize_callback' => 'sanitize_key',
),
),
'callback' => function ( WP_REST_Request $request ) {
$query = new WP_Query( array(
'post_type' => 'course',
'post_status' => 'publish',
'posts_per_page' => 20,
'meta_query' => array(
array(
'key' => 'level',
'value' => $request->get_param( 'level' ) ?? '',
'compare' => '!=',
),
),
) );
$items = array_map(
fn( WP_Post $p ): array => array(
'id' => $p->ID,
'title' => get_the_title( $p ),
'slug' => $p->post_name,
'level' => get_post_meta( $p->ID, 'level', true ),
),
$query->posts
);
return rest_ensure_response( $items );
},
) );
} );