https://codex.wordpress.org/AJAX_in_Plugins
https://www.damiencarbery.com/2017/02/simple-demo-of-ajax-code-for-wordpress/ (주로 참고)
https://blog.changwoo.pe.kr/wp-ajax-사용할-때-작은-팁들
위 3개 문서를 읽고 최대한 간략히 정리해본다.
Contents
1. 기본 구조
- .html (또는 .php) : ajax를 호출할 화면 정의
- .php (ajax enqueue) : ajax .js 를 등록하고, server 단의 값을 전달한다.
- .php (ajax handler) : client의 .js 호출에 따라 처리되어질 로직을 담는다.
- .js : 위 .html의 이벤트 발생 시(예: 버튼 클릭), 2번에서 전달된 값을 사용하여, 3번 로직을 호출한다. 호출된 로직의 결과값을 전달받아 client 단에서 처리해준다.
위 기본 구조를 적용한 ajax-example-plugin 이라는 플러그인을 만들어보자.
플러그인은 2개의 파일로 구성된다.
- ajax-example-plugin.php
- dc-ajax-demo.js
2. .html
ajax-example-plugin.php
<?php /* Plugin Name: ajax example Plugin Plugin URI: https://bekseju9n.pe.kr Version: 1.0 */ function aj_ajax_demo_shortcode() { $count_posts = wp_count_posts('post'); $count_pages = wp_count_posts('page'); return '<button class="count_btn" data-type="post" type="button">Get Post Count</button><div id="post_count">?</div> <button class="count_btn" data-type="page" type="button">Get Page Count</button><div id="page_count">?</div> <!-- List the post and page count so that we can see that the ajax results are correct. --> <p>Post Count: '.$count_posts->publish.'</p> <p>Page Count: '.$count_pages->publish.'</p>'; } add_shortcode('ajax_demo', 'aj_ajax_demo_shortcode');
ajax_demo라는 shortcode를 입력하면 post, page에 2개의 버튼을 출력하는 코드이다.
뒷부분에서 설명될 .js 파일에서 .count_btn 클래스의 event에 호출되고, #post_count 아이디에 해당하는 div 태그 안에 결과값을 출력하게 된다.
3. .php (ajax enqueue)
ajax-example-plugin.php
add_action( 'wp_enqueue_scripts', 'aj_enqueue_scripts' ); function aj_enqueue_scripts() { wp_register_script( 'aj-demo', plugin_dir_url( __FILE__ ). 'dc-ajax-demo.js', array('jquery')); // The second parameter ('aj_ajax_url') will be used in the javascript code. wp_localize_script( 'aj-demo', 'aj_ajax_demo', array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'aj_demo_nonce' => wp_create_nonce('aj-demo-nonce') )); // Note that the first parameter of wp_enqueue_script() matches that of wp_localize_script. wp_enqueue_script( 'aj-demo'); }
위 코드는 dc-ajax-demo.js 파일을 aj-demo라는 handle name으로 등록하고, 이 aj-demo 스크립트에 aj_ajax_demo 오브젝트 이름으로, ajax_url과 aj_demo_nonce의 서버 단 데이터를 넘겨준다. 1
4. .php (ajax handler)
ajax-example-plugin.php
add_action( 'wp_ajax_nopriv_aj_ajax_demo_get_count', 'aj_ajax_demo_process' ); // For non logged in users add_action( 'wp_ajax_aj_ajax_demo_get_count', 'aj_ajax_demo_process' ); // For logged in users. function aj_ajax_demo_process() { check_ajax_referer( 'aj-demo-nonce', 'nonce' ); // This function will die if nonce is not correct. $post_type = sanitize_text_field($_POST['post_type']); if (post_type_exists($post_type)) { $count_posts = wp_count_posts($post_type); wp_send_json($count_posts->publish); } wp_send_json_error(); wp_die(); }
wp_ajax_nopriv_***, wp_ajax_*** 형태로 action을 추가한다. 뒤에 설명할 .js 파일에서 위 ***을 호출하면, wordpress는 여기에 등록된 handler를 실행하게 된다. 위 코드에선 aj_ajax_demo_get_count가 action의 이름이 된다.
handler 코드의 첫번째 단계는 nonce 체크이다. aj-demo-nonce 스트링이 위에서 wp_localize_script()를 통해 전달되었고, 이 값을 nonce로 되돌려 받아 체크하게 된다. 2
nonce가 정상임을 확인하면, sanitize_text_field() 함수를 사용하여 태그나 위험한 문자들을 제거한다. 그리고 전달받은 post_type에 해당하는 $count_posts를 wp_send_json 함수를 통해 다시 .js로 전달한다.
5. .js
dc-ajax-deml.js
jQuery(document).ready( function(){ jQuery('.count_btn').on('click', function(e) { var post_type = jQuery(this).data( 'type' ); // Get post type via the 'data-type' attribute of the button. jQuery('#'+post_type+'_count').html('?'); // Clear existing value. e.preventDefault(); jQuery.ajax({ url : aj_ajax_demo.ajax_url, // Note that 'aj_ajax_demo' is from the wp_localize_script() call. type : 'post', data : { action : 'aj_ajax_demo_get_count', // Note that this is part of the add_action() call. nonce : aj_ajax_demo.aj_demo_nonce, // Note that 'aj_demo_nonce' is from the wp_localize_script() call. post_type : post_type }, success : function( response ) { jQuery('#'+post_type+'_count').html(response); // Change the div's contents to the result. }, error : function( response ) { alert('Error retrieving the information: ' + response.status + ' ' + response.statusText); console.log(response); } }); }); });
참고로 위 스타일 외에 codex에서 설명된 스타일도 참고해보자. 3
6. 적용 결과
위 코드들의 적용결과는 다음과 같다.
Post Count: 118
Page Count: 8
7. [추가] WP AJAX 사용할 때 작은 팁들 요약
(1) 비로그인 사용자를 위한 wp_ajax_nopriv_* 훅이 있다
.js 파일의 ajax 코드는 반드시 action 값을 가지고 있어야 한다. action에 주어진 값에 해당하는 * handler 함수를 호출하게 된다.
(2) GET/POST를 구분하라
get은 조회, post는 데이터 변경에 사용하자.
(3) nonce는 꼭 써라
단순 조회가 아니라면 nonce는 꼭 쓰도록 하자.
(4) 자바스크립트는 어지간하면 분리하여 작성하자
디버깅이 어려워진다.
(5) 자바스크립트는 PHP처럼 타입 저글링이 일어나지 않음에 유의하라
(6) wp_send_json_*() 함수를 써서 응답하라
(7) <?php 태그, 함부로 열고 닫는 거 아니다
Footnotes
- script 등록 과정은 register, localize, enqueue 순을 따라야 한다. 자세한 내용은 확인 필요
- 참고문서 3번에 따르면 nonce를 사용하는 방법으로
- form 내부에 hidden value로 저장
- 스크립트 로컬라이즈 시 별도로 nonce 값을 JSON으로 전달
- https://codex.wordpress.org/AJAX_in_Plugins#Separate_JavaScript_File
2 Responses