WordPressでajaxの基本的なやり方

WordPressに備わっているajaxについて、手順などをまとめます。もっといい方法、や修正などあったら教えてくださいましな。

今回作ったのは、タクソノミーによる絞込の検索フォームを作成する際に、階層を持つタクソノミーのドロップダウンを2つ用意して、親ターム選択用のドロップダウンでタームが選択されたら、子タームが取得されてもうひとつのドロップダウンの内容が変わる、というものです。

スクリーンショット 2014-08-25 19.32.43

意図する動き

どのように動くのか。

  1. ひとつめのドロップダウンで、タームが選択される
  2. ひとつめのドロップダウンで選択されたタームのIDがWordPressに送信される
  3. タームのIDを受け取ったWordPressが、そのIDのタームの子タームのIDと名前をjsonで返す
  4. IDとタームを受け取ったら、ふたつめのドロップダウンのoptionを書き換える

親タームが選択された、というイベントをきっかけとして、WordPressに親タームのIDを送信して、WordPressからはその親を持つ子タームのIDと名前をjsonで返す、戻ってきたjsonデータをもとに、optionを書き換える、という流れになります。

プラグインの作成の手順

そのためのプラグインを作る手順は以下です。

  1. WordPressのajax用の仕組みを使って、通信経路を作る
  2. レスポンスする関数を作って登録する
  3. 受け取ったレスポンスデータを扱って、htmlを書き換える

javascriptファイルの登録とphpからのデータの受け渡し

WordPressには、ajaxの仕組みがもとから付いています。この記事を読むと分かりますが、あんまり分かりやすい感じがないです。(現在、整備が進行中の json rest api が、今後もっと使われていくことになると思います。)

// WordPressのajaxの仕組みを利用するために、
// 1) js を登録。
// 2) また、javascriptが扱うデータをphpから渡す
add_action( 'wp_enqueue_scripts', '_child_search_script' );
function _child_search_script(){
    $path = get_template_directory_uri() . '/js/nskw-ajax.js';
    wp_enqueue_script(  'child-search-onload', $path, array('jquery'), '', true );
    wp_localize_script(
        'child-search-onload',
        'CHILDSEARCH', 
        array(
            'endpoint' => admin_url( 'admin-ajax.php' ),
            'action'   => 'child_search',
            'secure'   => wp_create_nonce( 'childsearch' )
        )
    );
}

まずは、普通にjavascriptを登録しています(wp_enqueue_script)。次に、wp_localize_script()という関数を使って、phpからjavascriptにデータを受渡しています。この関数は、javascriptには国際化i18n・地域化L10nの仕組みが無いために、phpからデータを渡しましょう、という目的のためのものです。WordPressは急速にjavascriptの分量を増やしていくと思われますので、jsで扱われるデータの翻訳についても仕組みが整えられていくようです。

ローカライズ(翻訳)用の仕組みを使ってphpからjsにデータを渡している感じなのですね。使い方は、wp_localize_script( $データを渡すスクリプトのハンドル名, $データを格納する変数の名前, arrray(dataそのもの) ); と言った感じです。

wp_localize_script()の3つ目の引数は連想配列で、これらのデータが、この例では、CHILDSEARCH.endpoint, CHILDSEARCH.action, CHILDSEARCH.secureのようにjavascriptで扱えるようになります。

データが登録されたjavascriptで、alert( CHILDSEARCH.secure );のように使えるということです。まどろっこしいですね。。

endpointは、WordPressがajax通信を受け付けるエンドポイントです。プラグインの場合、決め打ちでURLを作ってしまうと、環境によって動かなくなるので、admin_url( ‘admin-ajax.php’ );を使って、どんな環境でも正しいURLになるようにします。

javascriptからのデータの送受信、

実際のjavascriptは以下のようになっています。

$(function(){

    /* 親のselectが変更されたら */
    $("#parent-select-id").change(function(){

        /* 子selectを表示させつつ */
        $("#children-select").show("slow");
        
        /* 親selectの値を取得して、ajanx送受信用の関数に渡す */
        parentArea = $(this).val();
        runAjax(parentArea);

    });

});

/* データの送受信用の関数 */
function runAjax(parentArea) {
    
    /* wp_localize_scriptから受け取った
       endpoint, secureと、
       親タームのIDを送ってる */
    $.post(
        TOURSEARCH.endpoint, 
        {
    
            action: TOURSEARCH.action,
            parent_id: parentArea,
            secure: TOURSEARCH.secure
    
        }, 
        function(response){
            
            /* レスポンスを処理用の関数に渡す */
            makeOptions(response);

        }
    );
    
}

/* 受信したデータの処理とhtmlの書き換え */
function makeOptions(response) {

    $("#children-select").html("");
    emptyoption = '<option value="">---</option>';
    $("#children-select").append(emptyoption);
    $(response).each(function(){
        options = '<option value="' + this.id + '">' + this.name + '</option>';
        $("#children-select").append(options);
    });
    
}

ポイントは、jQuery.post() | jQuery API Documentationを利用して、送信して受信してるところです。urlとデータにwp_localize_script()から渡されたデータを利用してます。

WordPress側の処理

最後に、WordPress側の処理です。

親タームIDを受け取って、子タームのIDと名前のjsonデータを戻します。

ajax通信用の関数の登録方法もだいぶ変わってます。アクションフックを使ってはいますが、以下の形なので、ちょっと混乱しました。

add_action( 'wp_ajax_関数名',        '_関数名');
add_action( 'wp_ajax_nopriv_関数名', '_関数名');
function _関数名(){
    // 定義をここに

    // 最後にdie();しないと止まらない
    die();
}

実際には以下のような形にしました。

// ajax、非同期通信で送信されてきたリクエストに返答する関数を登録する
add_action( 'wp_ajax_child_search',        '_child_search');
add_action( 'wp_ajax_nopriv_child_search', '_child_search');
function _child_search(){

    check_ajax_referer( 'toursearch', 'secure' );
    
    $parent_id = intval( $_POST['parent_id'] );

    $args = array(
        'child_of' => $parent_id, // ここに受け取った
    );
    $children_arr = get_terms( 'taxonomyname', $args );
    $children = array();
    foreach ( $children_arr as $c ) {

        $children[] = array(
            'id'   => esc_js( (int)$c->term_id ),
            'name' => esc_js( $c->name )
        );
    }

    // PHPの配列をJSONに変換して出力
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode( $children );
    die();
    
}

実際にはもう少し、エラー処理などを足していきますが、基本は上記のような形です。

ポイントは、以下だと思います。

  • 関数自体の登録の方法が変わってる
  • 最初にcheck_ajax_referer( ‘wp_create_nonceで使った名前’, ‘送られてきたpostデータのキー’ );でチェックする。ノンスがおかしければdie()されます。
  • parent_idを$_POSTで受け取って使う
  • 当然だけど、WordPressの関数が使えて嬉しい。ときどき、sqlを書くチュートリアルとかがあるけど、別に必要ないはず。
  • jsonで返すときのheader()とjson_encodeの感じ

というわけで、

  1. javascriptとそのデータの登録: enqueue と localize とか
  2. javascriptからのデータの送信: jQuery.post とか
  3. 関数の登録と返信方法

でありました。

参考リンク

↓ プラグインを作る方々への本、書きました。 ↓

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

WordPressでajaxの基本的なやり方」への2件のフィードバック

  1. ひっしーさん、

    ありがとうございます。次からこれにします。