2026年5月20日
2026年5月20日
WordPressプラグインでAJAX処理を実装する方法
はじめに
WordPressのAJAX処理は wp_ajax_{action} フックと wp-admin/admin-ajax.php を通じて実装します。wp_localize_script() でJavaScriptにnonce・URLを渡し、セキュアなAJAX通信を実現する方法を解説します。
症状・原因
- ページリロードなしでデータを保存・取得したい
- フォームの非同期送信を実装したい
- ログイン済みと非ログインユーザー両方でAJAXを使いたい
- WordPressのAJAXとREST APIの使い分けを知りたい
解決手順
ステップ1:JavaScriptファイルを登録してnonceを渡す
// プラグインファイル
add_action('wp_enqueue_scripts', function(): void {
wp_enqueue_script(
'myplugin-ajax',
plugin_dir_url(__FILE__) . 'js/ajax.js',
['jquery'],
'1.0.0',
true // フッターに出力
);
// JavaScriptにPHPの値を渡す
wp_localize_script('myplugin-ajax', 'mypluginAjax', [
'ajaxUrl' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('myplugin_ajax_nonce'),
'i18n' => [
'sending' => '送信中...',
'success' => '保存しました',
'error' => 'エラーが発生しました',
],
]);
});
ステップ2:PHPでAJAXハンドラーを登録する
// ログイン済みユーザー向け
add_action('wp_ajax_myplugin_save_note', 'myplugin_ajax_save_note');
// 非ログインユーザーも許可する場合
add_action('wp_ajax_nopriv_myplugin_save_note', 'myplugin_ajax_save_note');
function myplugin_ajax_save_note(): void {
// nonce 検証(セキュリティチェック)
check_ajax_referer('myplugin_ajax_nonce', 'nonce');
// 権限チェック(任意)
if (!current_user_can('edit_posts')) {
wp_send_json_error(['message' => '権限がありません'], 403);
}
// 入力値を取得・サニタイズ
$title = sanitize_text_field($_POST['title'] ?? '');
$content = wp_kses_post($_POST['content'] ?? '');
if (empty($title)) {
wp_send_json_error(['message' => 'タイトルは必須です'], 400);
}
// データを保存
$post_id = wp_insert_post([
'post_title' => $title,
'post_content' => $content,
'post_status' => 'publish',
'post_type' => 'post',
]);
if (is_wp_error($post_id)) {
wp_send_json_error(['message' => $post_id->get_error_message()], 500);
}
// 成功レスポンスを返す(wp_die()は不要)
wp_send_json_success([
'post_id' => $post_id,
'message' => '保存しました',
'edit_url' => get_edit_post_link($post_id),
]);
}
ステップ3:JavaScriptでAJAXリクエストを送る
// js/ajax.js
jQuery(function ($) {
$('#save-note-form').on('submit', function (e) {
e.preventDefault();
const $btn = $(this).find('[type="submit"]');
$btn.prop('disabled', true).text(mypluginAjax.i18n.sending);
$.ajax({
url: mypluginAjax.ajaxUrl,
method: 'POST',
data: {
action: 'myplugin_save_note', // wp_ajax_{action}
nonce: mypluginAjax.nonce,
title: $('#note-title').val(),
content: $('#note-content').val(),
},
success(response) {
if (response.success) {
alert(response.data.message);
console.log('投稿ID:', response.data.post_id);
} else {
alert(response.data.message || mypluginAjax.i18n.error);
}
},
error() {
alert(mypluginAjax.i18n.error);
},
complete() {
$btn.prop('disabled', false).text('保存');
},
});
});
});
ステップ4:Fetch APIを使ったモダンな実装
// jQuery不要のモダンな実装
document.getElementById('save-note-form')?.addEventListener('submit', async (e) => {
e.preventDefault();
const form = e.target;
const data = new FormData();
data.append('action', 'myplugin_save_note');
data.append('nonce', mypluginAjax.nonce);
data.append('title', form.querySelector('#note-title').value);
data.append('content', form.querySelector('#note-content').value);
try {
const res = await fetch(mypluginAjax.ajaxUrl, { method: 'POST', body: data });
const json = await res.json();
if (json.success) {
console.log('保存成功:', json.data);
} else {
console.error('エラー:', json.data?.message);
}
} catch (err) {
console.error('通信エラー:', err);
}
});
ステップ5:WP-CLIでAJAXをデバッグする
# admin-ajax.php のエンドポイントを確認
wp eval "echo admin_url('admin-ajax.php');"
# nonceを生成してテスト
wp eval "echo wp_create_nonce('myplugin_ajax_nonce');"
# curlでAJAXリクエストをシミュレート(管理者Cookieが必要)
curl -X POST https://example.com/wp-admin/admin-ajax.php \
-d 'action=myplugin_save_note&nonce=NONCE&title=テスト&content=本文'
# AJAXアクションの登録を確認
wp eval "global \$wp_filter; print_r(array_keys(\$wp_filter['wp_ajax_myplugin_save_note']->callbacks ?? []));"
ステップ6:REST APIとの使い分け
WordPress AJAX(admin-ajax.php):
→ jQueryが使える環境 / 既存のWordPressフックと連携
→ 非ログインユーザーには wp_ajax_nopriv_ が必要
→ セッション・Cookie認証が必要なケースに適している
REST API(/wp-json/):
→ モダンなJavaScript・外部アプリとの連携
→ Application Passwordで認証
→ GET/POST/PUT/DELETEをHTTPメソッドで使い分け
→ 外部からのアクセスやStateless APIに適している
注意事項
check_ajax_referer()は失敗時に自動的にwp_die()します。エラーハンドリングは不要ですwp_send_json_success()/wp_send_json_error()は内部でwp_die()を呼び出すため、その後のコードは実行されませんwp_ajax_nopriv_は認証不要のため、レートリミットや入力バリデーションを厳重にしてください
まとめ
WordPressのAJAXは wp_ajax_{action} フックにハンドラーを登録し、wp_localize_script() でnonce・URLをJavaScriptに渡します。check_ajax_referer() でCSRFを防ぎ、wp_send_json_success() / wp_send_json_error() でJSON形式でレスポンスを返します。