ajax in wordpress

Share on facebook
Facebook
Share on twitter
Twitter
Share on linkedin
LinkedIn
Share on print
Print

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개 문서를 읽고 최대한 간략히 정리해본다.


1. 기본 구조

  1. .html (또는 .php) : ajax를 호출할 화면 정의
  2. .php (ajax enqueue) : ajax .js 를 등록하고, server 단의 값을 전달한다.
  3. .php (ajax handler) : client의 .js 호출에 따라 처리되어질 로직을 담는다.
  4. .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_urlaj_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_postswp_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

  1. script 등록 과정은 register, localize, enqueue 순을 따라야 한다. 자세한 내용은 확인 필요
  2. 참고문서 3번에 따르면 nonce를 사용하는 방법으로

    1. form 내부에 hidden value로 저장
    2. 스크립트 로컬라이즈 시 별도로 nonce 값을 JSON으로 전달

    2가지를 설명하고 있다. 이 문서의 예제는 2번째 케이스가 된다.

  3. https://codex.wordpress.org/AJAX_in_Plugins#Separate_JavaScript_File

2 Responses

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다