WordPress から Ajax による通信処理を実装するメモ書きです。
検索機能を強化するために「カテゴリ」と「タグ」を使って絞り込める検索フォームを作りましたが、これを連動型にして親切設計にしたいなと思っています。
実装方法は Ajax 使った連動型のセレクトボックスしか思いつかないので、とりあえずこれでやってみるかという感じなのですが、一般のページではどのように Ajax を実装するのが良いかを調べてみました。
スポンサーリンク
WordPress の Ajax 実装方法
以前に、プラグイン用途で Ajax については調べていて、以下の様な記事を書いていました。
かなり簡略化してる記事で、Ajax 時の「nonce」認証には全く触れませんでしたが、これは会った方がセキュアになるので今回は改めて書きたいと思います。
以下で実装コードを書きながら要点を説明していきます。
WordPress で nonce 認証コードを吐き出す処理を追加
Ajax のリクエストは、「http://…/admin-ajax.php?action=myaction」みたいに WordPress 自身の admin-ajax.php にリクエストを出す必要があるのですが、nonce 認証を利用するには「送り側 (javascript)」と「受け側 (WordPress)」に一意の値が必要です。
wp_create_nonce( ‘hogehoge’ ) で hogehoge をキーにした none 認証のコードを作成できますが、これを javascript から取得するには、functions.php に以下のコードを書くとスマートになると思います。
wp_localize_script( $handle, 'MyAjax', array( 'url' => admin_url( 'admin-ajax.php' ), 'action' => 'my_ajax', 'token' => wp_create_nonce( 'hogehoge' ) // nonce 生成文字列 ) );
完全なコードは後で書きますが、これを実装すると HTML に以下の様なソースが追加されます。
<script> /* <![CDATA[ */ var MyAjax = {"url":"http:\/\/example.jp\/wp-admin\/admin-ajax.php","action":"my_ajax","token":"156fa7bcc0"}; /* ]]> */ </script>
ここに URL や nonce 認証用のコードが javascript の連想配列で吐出されるので、後は javascript から読み取って使うという具合です。
試しに、functions.php には以下の用なコードを書いてみました。
if ( ! is_admin() ) { // デフォルトで読み込まれる jquery を削除 function deregister_script() { wp_deregister_script( 'jquery' ); } // Google から jQuery を読み込み function register_script() { wp_register_script( 'jquery', '//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js', false, '1.10.2', true ); } // nonce 用スクリプトの登録 function register_nonce_script() { $jsdir = get_stylesheet_directory_uri(); $handle = 'myajax'; wp_register_script( $handle, "$jsdir/js/ajax.js", array( 'jquery' ), '1.0', true ); wp_localize_script( $handle, 'MyAjax', array( 'url' => admin_url( 'admin-ajax.php' ), 'action' => 'my_ajax', 'token' => wp_create_nonce( 'hogehoge' ) // nonce 生成文字列 ) ); } function add_script() { deregister_script(); register_script(); wp_enqueue_script( 'jquery' ); if ( is_single() ) { register_nonce_script(); wp_enqueue_script( 'myajax' ); } add_action( 'wp_enqueue_scripts', 'add_script' ); }
中でいくつかの関数に分けて登録するものや消すものを指定していますが、今回は新しく nonce 認証を利用する用に register_nonce_script() というのを書いてみました。
次にサーバ側の処理はこんな感じです。
function my_ajax() { header( 'Content-Type: application/json; charset=UTF-8' ); // nonce が POST され正しい情報である場合 if ( wp_verify_nonce( $_POST['token'], 'hogehoge' ) ) { echo json_encode( array( 'status' => 'OK' ) ); // nonce が POST されない、または不正な情報の場合 } else { echo json_encode( array( 'status' => 'NG' ) ); } die(); } add_action( 'wp_ajax_my_ajax', 'my_ajax' ); add_action( 'wp_ajax_nopriv_my_ajax', 'my_ajax' );
admin-ajax.php に渡すアクション名は my_ajax にしました。
WordPress 側はこれで以上です。
Ajax で nonce 認証コードを利用する
次はクライアント側の javascript を書いていきます。
動作用のデモコードとなりますがこんな感じに書いてみました。(ファイル名は ajax.js)
(function ($) { $("input:button[name=ajax]").click(function(){ sendData(MyAjax); }); $("input:button[name=ajax-no]").click(function(){ var NoToken = { "url" : MyAjax.url, "action": MyAjax.action, "token" : "hugahuga" }; sendData(NoToken); }); $("input:button[name=ajax-reset]").click(function(){ resultMsg("ここに結果が入ります"); }); function sendData(param) { $.ajax({ type : "POST", url : param.url, dataType: "json", async : true, data : { action: param.action, token : param.token }, }).done(function(callback){ if ( callback != null && callback.status == 'OK' ) { resultMsg("処理は成功しました"); } else { resultMsg("処理は失敗しました"); } }).fail(function(XMLHttpRequest, textStatus, errorThrown){ resultMsg("処理は失敗しました"); // エラー時のデバッグ用 //console.log(XMLHttpRequest); //console.log(textStatus); //console.log(errorThrown); }); return; } function resultMsg(msg) { $("input:text[name=result]").val(msg); return; } })(jQuery);
上記で読み込み設定をした通りテーマ内の js ディレクトリにこれをアップします。
後は以下のような HTML を書くと以下のデモと同じく動作します。
<input type="text" readonly="readonly" name="result" value="ここに結果が入ります"></input> <input type="button" name="ajax" value="nonce" /> <input type="button" name="ajax-no" value="no nonce" /> <input type="button" name="ajax-reset" value="リセット" />
nonce 有り無しの動作デモ
「nonce ボタン」は HTML より nonce 認証コードを読み取って正規の情報で POST、「no noce」ボタンは不正な nonce 認証コードを設定して POST という感じです。
ただ、CodeX にもある通り nonce 認証コードは完全にセキュアにできるという機構ではないので、その点は念頭に置いといたほうが良さそうです。
最後に、今回は参考にしたページは下記です。Ajax をセキュアに実装したい場合には非常に参考になると思います。