WordPressでのAjax実装方法

Ajax(エージャックス)を使うと画面遷移を伴わずにデータを呼び出したり、保存したりできます。ブラウザを更新せずに画面を変化させ、SPA(シングルページアプリケーション)っぽい挙動も実装できます。WordPress での Ajax はやや特殊ながら、お作法に沿って実装すれば比較的簡単なので、使い方をメモしました。

    /wp-admin/admin-ajax.php を利用

    WordPress では Ajax を利用するために標準で/wp-admin/admin-ajax.phpが用意されています。ここに Ajax でリクエストを投げると、用意した PHP の関数を呼び出すことができます。

    処理の流れ

    1. JavaScript から Ajax で admin-ajax.php に任意のアクション名[action]を投げる
    2. admin-ajax.phpからwp_ajax_[action]wp_ajax_nopriv_[action](非ログインユーザー用)のアクションフックに登録された関数を呼び出す
    3. 関数からレスポンスを返す

    PHP の値を JavaScript に渡す

    • admin-ajax.php のURL
    • nonce の値

    を動的に取得して JavaScript に渡す必要があります。いくつかのやり方があります。

    PHP にべた書きする

    const $ajax_url = '<?php echo admin_url( 'admin-ajax.php'); ?>';
    const $ajax_nonce = '<?php echo wp_create_nonce('wp_ajax_my_action'); ?>';

    シンプルで分かりやすいと感じるか、あんまりきれいな実装ではないと感じるかはあなた次第……。

    wp_localize_script()

    add_action( 'wp_enqueue_scripts', 'nora_ajax_demo_enqueue_scripts_by_localize_script' );
    function nora_ajax_demo_enqueue_scripts_by_localize_script(){
    	$nora_ajax_demo_object = array( 
    		'ajax_url' => admin_url( 'admin-ajax.php' ),
    		'ajax_nonce' => wp_create_nonce('wp_ajax_my_action'),
    	);
    	wp_enqueue_script( 'nora_ajax_demo', plugin_dir_url( __FILE__ ) . '/js/nora-ajax-demo.js', array('jquery') );
    	wp_localize_script( 'nora_ajax_demo', 'nora_ajax_demo_object', $nora_ajax_demo_object );
    }

    こういう感じでPHP側からインラインのスクリプトを追加できます。wp_enqueue_script()等で script を登録した”後”にコールする必要があります。

    出力

    <script type='text/javascript' id='nora_ajax_demo-js-extra'>
    /* <![CDATA[ */
    var nora_ajax_demo_object = {"ajax_url":"http:\/\/example.com\/wp-admin\/admin-ajax.php","ajax_nonce":"xxxxxxxxxx"};
    /* ]]> */
    </script>

    本来の用途ではないので推奨ではなさそうだが

    Though localization is the primary use, it was often used to pass generic data from PHP to JavaScript, because it was originally the only official way to do that. wp_add_inline_script() was introduced in WordPress Version 4.5, and is now the best practice for that use case. `wp_localize_script()` should only be used when you actually want to localize strings.

    wp_localize_script() | Function | WordPress Developer Resources

    ということで「PHP の値を JavaScript に渡す関数」としていろんなところで紹介されていますが、本来は文字列のローカライズが目的の関数なので、wp_add_inline_script()が推奨されています。ただ

    という点からみて、普通にこっちを使ってもいいのではと思います(本記事ではいちおうwp_add_inline_script()で進めます)。

    wp_add_inline_script()

    add_action( 'wp_enqueue_scripts', 'nora_ajax_demo_enqueue_scripts_by_add_inline_script' );
    function nora_ajax_demo_enqueue_scripts_by_add_inline_script(){
    	$nora_ajax_demo_vars = '
    	const ajax_url = "' . admin_url( 'admin-ajax.php' ) . '";
    	const ajax_nonce = "' . wp_create_nonce('wp_ajax_my_action') . '";';
    
    	// または
    
    	$nora_ajax_demo_object = 'const nora_ajax_demo_object = ' . json_encode( array( 
    		'ajax_url' => admin_url( 'admin-ajax.php' ),
    		'ajax_nonce' => wp_create_nonce('wp_ajax_my_action'),
    	));
    
    	wp_enqueue_script( 'nora_ajax_demo', plugin_dir_url( __FILE__ ) . '/js/nora-ajax-demo.js', array('jquery')  );
    	wp_add_inline_script( 'nora_ajax_demo', $nora_ajax_demo_object, 'before' );
    }

    WordPress4.5 から登場した関数です。

    渡し方は2種類書いてみましたが、公式のドキュメントを見た感じは後者の書き方が基本っぽいので以下これでいきます。なお、js側で利用時、JSON.parse()は XSS の恐れがあり使わないほうがよい。らしい。

    出力

    <script type='text/javascript' id='nora_ajax_demo-js-before'>
    const nora_ajax_demo_object = {"ajax_url":"http:\/\/test.local\/wp-admin\/admin-ajax.php","ajax_nonce":"d7c71f1ff9"}
    </script>

    このようなのがハンドルで指定したスクリプトの前後に出力されます。

    JavaScript(フロント側の実装)

    jQuery(document).ready(function($) {
    	$('.nora_ajax_demo_btn').click(function(){
    		$.ajax({
    			type: "POST",
    			url: nora_ajax_demo_object.ajax_url,
    			data: {
    				'action': 'nora_ajax_demo_action',
    				'nonce' : nora_ajax_demo_object.ajax_nonce,
    				'key1'  : 'val1',
    				'key2'  : 'val2',
    				'dataType' : 'json'
    			},
    		}).done(function(ret){
    			// 成功時の処理
    			console.log(ret);
    		}).fail(function(){
    			// 失敗時の処理
    		});
    	});
    });

    サンプルは jQuery です。actionにアクションフックに使うアクション名を指定。その他、送りたい変数を適宜設定。セキュリティ上、nonce の検証はなくてもいい場合はありますが基本的にやるもの、と思っておいた方が安全で良いと思います。

    サンプルでは変数retでレスポンスを受けています。レスポンスで配列で受け取りたい場合は、'dataType' : 'json'と指定したうえで json エンコードしたものを返します。

    PHP(サーバー側の実装)

    add_action( 'wp_ajax_nora_ajax_demo_action', 'nora_ajax_demo' );
    add_action( 'wp_ajax_nopriv_nora_ajax_demo_action', 'nora_ajax_demo_nopriv' );
    function nora_ajax_demo(){
    	$nonce = check_ajax_referer('wp_ajax_my_action','nonce', false);
    	if( !$nonce ){
    		echo 'nonce error';
    		wp_die();
    	}
    	$val1 = $_POST['key1'];
    	$val2 = $_POST['key2'];
    	// 好きな処理
    	$ret = array(
    		'hoge',
    		'fuga'
    	);
    	header("Content-type: application/json; charset=UTF-8");
    	echo json_encode($ret); // 戻り値をechoする
    	wp_die();
    }
    
    function nora_ajax_demo_nopriv(){
    	check_ajax_referer('wp_ajax_my_action','nonce');
    	// 非ログインユーザー処理
    	wp_die();
    }

    JavaScript で指定した action でwp_ajax_[action]wp_ajax_nopriv_[action]というアクションフックを用意して、処理の関数を書きます。ログインユーザー用と非ログインユーザー用でフックが異なるので注意。

    レスポンスを返すときはechoし、処理はwp_die();で終わらせます。

    サンプルでは配列を json で返すため、Content-type を指定してあります。

    まとめ

    以上、WordPress での Ajax 実装について毎回調べちゃうので、自分用の備忘録のつもりでまとめました。ググるとwp_add_inline_script()はともかく、nonce の存在にも触れていないブログ記事もでくるので、それらより上位に表示されたら、世のセキュリティ強化に僅かにでも貢献出来るのかな?ともうっすら期待しつつ。

    サポートが必要ですか?

    ご質問・お見積り依頼はお気軽にどうぞ

    お問い合わせはこちら
    シェア
    野良人 代表
    新免祥太
    1988年岡山生まれ。外食企業のWEB・EC担当を経験したのち、2013年12月より「野良人(のらんど)」の屋号で独立しWEBデザイン・プログラミングなどWEBサイト制作の工程全般を請け負っています。お気軽にご相談ください。
    広告
    次の記事(2022/03/10)
    WordPressのカテゴリーアーカイブをタグで絞り込み検索
    前の記事(2021/12/14)
    WP-Members のログインフォームや新規登録フォームをカスタマイズ
    記事一覧