かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

Ajaxを使ってWordPressからコンテンツを取得したい。

WordPress製のサイトに独自のコンテンツなどを取得できるAjaxを作成する方法のメモ

  1. 呼び出すアクション名を決める
  2. Ajax送信先をjsから使えるように出力する
  3. Ajaxで呼び出される関数を作成する (PHP)
  4. フロントからAjaxでの呼出しを作成する (javascript)

1. 呼び出すアクション名を決める

アクション名はPHPの関数名やnoce、jsのAjax内などで何度も使うので、どんな仕様にするか決めて仕様に合ったアクション名を先に決めておくのが良いと思います。

今回は my-ajax-action というアクション名にします。

2. Ajax送信先のパスなどの出力

WordPressAjaxのリクエス送信先 /wp-admin/admin-ajax.php のパスやnoneなどの情報をjavascriptグローバル変数として出力する

<?php // function.php
function my_enqueue_scripts() {
  $handle = 'my-script';
  // Ajaxの呼出しが書かれているスクリプトのパス
  $jsFile = 'path/to/myscript.js';
  
  wp_register_script($handle, $jsFile, ['jquery']);
  
  // 1.で決めたアクション名
  $acrion = 'my-ajax-action';
  // 配列をJSのオブジェクトに変換したscriptを出力する
  wp_localize_script($handle, 'MY_AJAX', [
    'api'    => admin_url( 'admin-ajax.php' ),
    'action' => $acrion,
    'nonce'  => wp_create_nonce( $acrion ),
  ]);
  
  wp_enqueue_script($handle);
}
add_action( 'wp_enqueue_scripts', 'my_enqueue_scripts' );

$handleで指定された myscript.js の出力タグの前に次のようなスクリプトが出力されます。

<script type='text/javascript'>
/* <![CDATA[ */
var MY_AJAX = {
  "api": "http:\/\/example.com\/wordpress\/wp-admin\/admin-ajax.php",
  "action": "my-ajax-action",
  "nonce": "生成されたNONCE値"
}
/* ]]> */
</script>

※ 実際には1行で出力されます。グローバル変数になっちゃうので、ちょっとイケてない感あります…

複数のアクションを作成する場合は、アクションとそれに対応したnonceが取得しやすいように配列をネストするなどして工夫してください。

3. 呼び出される関数の作成 (PHP)

3.1 Ajaxから呼び出される関数を定義する

add_action アクションフックで、Ajaxから呼び出される関数を登録する。

<?php // function.php
function my_ajax_event() {
}
add_action( 'wp_ajax_my-ajax-action', 'my_ajax_event' );
add_action( 'wp_ajax_nopriv_my-ajax-action', 'my_ajax_event' );
  • wp_ajax_{action名} … ログインユーザーの時、呼び出される
  • wp_ajax_nopriv_{action名} … 非ログインユーザーの時、呼び出される

フロントから呼び出される場合は、両方のアクションフックを設定する必要がある。
管理画面で使うだけなら、常にログインユーザーなので wp_ajax_{action名} の方だけでOK。

3.2 Ajaxで呼び出される関数の処理を作成する

<?php // function.php
function my_ajax_event() {
  // wp_create_nonce の引数に渡したものと同じ アクション名
  $action = 'my-ajax-action';
  
  // nonceのチェック
  if( check_ajax_referer($action, 'nonce', false) ) {
    $data = [];

    // Ajax(post)のdataから渡される値を使用する場合は $_POST から取得する (適時エスケープ)
    $id = intval( $_POST['post_id'] );
    $name = esc_html( $_POST['name'] );
    
    /* wordpressから色々取得したり、Ajaxで返すデータ作成する */
    
    // 配列をjson形式にエンコード
    $data = json_encode($data);
  } else {
    // エラー
    status_header( '403' );
    $data = 'Forbidden';
  }

  // Ajaxに返す
  header( 'Content-Type: application/json; charset=UTF-8' );
  echo $data;

  die();
}
add_action( 'wp_ajax_my-ajax-action', 'my_ajax_event' );
add_action( 'wp_ajax_nopriv_my-ajax-action', 'my_ajax_event' );

nonceのチェック

check_ajax_referer( $action, $query_arg, $die )
  • $action (string)
    nonceのアクション名
    nonce作成時の wp_create_nonce() に渡したアクション名と同じ文字列を指定する
  • $query_arg (string)
    $_REQUESTで渡される配列の nonce が格納されているキーを指定
    上の例の場合は data: { nonce: 値 } としてAjaxから送ればOK
  • $die (boolean) default: true
    trueの時 nonce が無効なら die() する
    falseの時 nonce のチェック結果を true / false で返す

Ajax(post)のdataで渡される値は$_POSTで取得することができます。
nonceのチェック関数は内部では$_REQUESTから取得している様なので、$_REQUESTの方がget/postどちらでも取得できるで良いのかもしれません。

Ajaxで呼び出される関数の最後に die() がないと返されるデータの最後に0が追加されてしまうので、忘れないようにdieしておく必要があります。

4. Javascriptの作成 (Ajax呼出し)

後はフロントのjavascriptからAjaxで呼び出すだけです。
URLやアクション名は 2. で作成したグローバル変数から使用します。

// global MY_AJAX
"use strict";
$(function() {
  $.ajax({
    url: MY_AJAX.api,
    type: 'post',
    data: {
      // 呼び出すアクション名
      action: MY_AJAX.action,
      // アクションに対応するnonce
      nonce: MY_AJAX.nonce,
      // ▼ その他 渡したいデータがあれば適時 ▼
      post_id: 12345,
      name: 'name'
    }
  })
  .done(function( res ) {
    console.log( res );
  })
  .fail(function( jqXHR, textStatus, errorThrown ) {
    console.log( jqXHR, textStatus, errorThrown, arguments);
  });
});

 
これで、Ajaxを使ってWordPressから独自のコンテンツとか値を取得することができるようになりました。
Ajaxを使うために出力するjavascriptの変数がglobal変数になってしまうのが、やっぱイケてない感じなので、どうにか出来ないものかと思っています。。。


[参考]

世界一わかりやすいWordPress 導入とサイト制作の教科書 (世界一わかりやすい教科書)

世界一わかりやすいWordPress 導入とサイト制作の教科書 (世界一わかりやすい教科書)