페이지를 다시 로드하지 않고 양식 제출: WordPress의 AJAX 구현
게시 됨: 2022-03-10페이지를 다시 로드하지 않고 양식을 보내고 싶은 경우 사용자가 입력할 때 제안 사항을 표시하는 미리보기 검색 기능을 제공하거나 문서를 자동 저장하려면 AJAX ( XHR 이라고도 함)가 필요합니다. 비하인드 스토리 요청이 서버로 전송되고 데이터가 양식으로 반환됩니다. 페이지에서 작업을 수행한 후 로더 애니메이션을 볼 때마다 아마도 서버에 제출되는 AJAX 요청일 것입니다.
이 기사에서는 AJAX 호출을 생성하고 처리하는 전체 프로세스를 안내합니다. AJAX 호출 방법뿐만 아니라 WordPress가 즉시 개발자에게 제공하는 기능을 사용하여 가장 좋은 방법으로 호출하는 방법을 배우게 됩니다. 독자가 웹사이트에서 발견할 수 있는 버그에 대한 정보가 포함된 보고서를 관리자에게 보낼 수 있는 간단한 플러그인을 구축할 것입니다.

기사 끝에서 작업 예제를 다운로드하고 전체 코드를 검토할 수 있습니다.
파헤쳐보자!
아약스
"페이지를 새로고침하지 않고"가 핵심 문장입니다. AJAX는 Asynchronous JavaScript And XML 의 약자입니다. 처음에는 서버에서 반환되는 데이터가 XML로 되어 있기 때문입니다. 그러나 JavaScript가 더 좋아하는 JSON으로 보내는 것이 더 쉽습니다.
우리는 AJAX를 사용하여 이메일을 보낼 것입니다. 프론트 엔드에서는 할 수 없으므로 백엔드를 호출해야 합니다. 일반적으로 POST 요청을 서버에 보내고 처리하고 사용자를 양식이 있는 페이지로 다시 리디렉션합니다. 이 반복에서는 페이지를 다시 로드하고 싶지 않습니다. 대신 JavaScript로 양식 데이터를 캡처한 다음 응답을 처리하기 위해 서버에 비동기 요청을 보낼 백엔드를 직접 호출합니다.
WordPress AJAX가 작동하려면 세 가지가 필요합니다. 그 중 다섯 가지가 제대로 작동 합니다 . 이것들은:
- AJAX 작업을 위한 개체
- 자바스크립트 스크립트
- 워드프레스 작업
- 보호
- 오류 처리
각각에 대해 자세히 살펴보겠습니다.
물체
우리의 대상은 형식입니다. 이것은 JavaScript로 처리할 우리의 일입니다. WordPress 플러그인에 필요한 헤더가 있는 파일을 만들고 내부에 빈 개체를 넣는 것부터 시작했습니다. 결국 플러그인 클래스의 새 인스턴스를 만들고 있습니다.
<?php /* Plugin Name: Report a bug Description: Allow your visitors to report a bug in your articles Author: Jakub Mikita Author URI: https://underdev.it Version: 1.0 License: GPL2 Text Domain: reportabug */ class Report_a_bug { } new Report_a_bug();
여기에서 약간의 OOP를 사용하고 있지만 고급 방식은 사용하지 않을 것입니다. 코드는 별도의 기능을 사용하여 절차적으로 작성될 때도 잘 작동합니다. 그러나 WordPress 플러그인 내의 객체에는 한 가지 장점이 있습니다. 함수에 접두사를 붙일 필요가 없습니다. 클래스 이름만 고유하면 됩니다.
사용자에게 양식을 표시해 보겠습니다. 우리는 the_content
필터에 연결하고 모든 게시물의 끝에 양식을 포함할 것입니다. 클래스의 생성자에서 필터를 추가했습니다.
public function __construct() { add_filter( 'the_content', array( $this, 'report_button' ), 10, 1 ); }
그리고 HTML 형식으로 콜백 메서드를 만들었습니다.
public function report_button( $content ) { // display button only on posts if ( ! is_single() ) { return $content; } $content .= '<div class="report-a-bug"> <button class="show-form" data-post_>' . __( 'Report a bug', 'reportabug' ) . '</button> <textarea class="report-a-bug-message" placeholder="' . __( 'Describe what\'s wrong...', 'reportabug' ) . '"></textarea> <p class="report-a-bug-response"></p> </div>'; return $content; }
양식에는 필요한 모든 마크업이 있습니다.
- 양식을 표시하고 메시지를 보내는 버튼.
-
textarea
; - 응답을 위한 컨테이너입니다(나중에 사용할 것입니다).
버튼에는 현재 게시물 ID를 저장하는 data-post_id
속성이 있습니다. 기사를 식별하기 위해 JavaScript에서 이것을 잡을 것입니다.
우리는 몇 가지 기본 스타일만 필요하므로 wp_enqueue_scripts
작업과 해당 콜백을 사용하여 자체 스타일시트를 등록해 보겠습니다.
public function __construct() { add_filter( 'the_content', array( $this, 'report_button' ), 10, 1 ); add_action( 'wp_enqueue_scripts', array( $this, 'scripts' ) ); } function scripts() { wp_enqueue_style( 'report-a-bug', plugin_dir_url( __FILE__ ) . 'css/style.css' ); }
스타일시트 자체는 매우 간단합니다. 디자인을 정리하고자 합니다.
.report-a-bug-message { display: none; margin-top: 1em; } .report-a-bug-response { margin-top: 1em; }
버튼 모양은 다음과 같습니다.

스크립트
우리는 개체에 생명을 불어넣을 준비가 되어 있습니다. 일반 JavaScript에서 수행하는 대신 WordPress가 모든 페이지에서 기본적으로 로드하는 jQuery를 사용할 것입니다.
기존 스크립트 방식에서는 wp_enqueue_script
함수를 이용하여 JS 파일을 추가하겠습니다.
function scripts() { wp_enqueue_style( 'report-a-bug', plugin_dir_url( __FILE__ ) . 'css/style.css' ); wp_enqueue_script( 'report-a-bug', plugin_dir_url( __FILE__ ) . 'js/scripts.js', array( 'jquery' ), null, true ); // set variables for script wp_localize_script( 'report-a-bug', 'settings', array( 'send_label' => __( 'Send report', 'reportabug' ) ) ); }
또한 번역된 버튼 레이블을 JS에 전달하기 위해 wp_localize_script
함수를 사용하고 있습니다. JavaScript에는 gettext
함수가 없으므로 여기에서 수행해야 합니다. 이 함수는 스크립트에서 직접 액세스할 수 있는 설정 개체를 만듭니다.
스크립트에서 버튼 클릭을 수신할 것입니다. 그런 일이 발생하면 textarea
을 표시하고 양식을 보내는 두 번째 클릭을 수신하도록 버튼 클래스를 전환합니다.
( function( $ ) { $( document ).ready( function() { $( '.report-a-bug' ).on( 'click', '.show-form', function( event ) { // change label and switch class $( this ).text( settings.send_label ).removeClass( 'show-form' ).addClass( 'send-report' ); // show textarea $( '.report-a-bug-message' ).slideDown( 'slow' ); }) }); })( jQuery );
현재 진행 상황은 다음과 같습니다.

textarea
드롭다운AJAX 요청을 생성하기 가장 좋은 시간입니다!
WordPress에 대한 AJAX 요청
AJAX 요청을 보내려면 요청된 URL이라는 단 하나의 매개변수만 있으면 됩니다. WordPress에는 AJAX용 특수 파일이 있으므로 직접 만들 필요가 없습니다. /wp-admin/admin-ajax.php
입니다.
wp-admin
영역에 있는 한 이 파일 URL은 JS의 ajaxurl
변수에서 사용할 수 있습니다. 프론트 엔드에서 이 변수를 직접 전달해야 합니다. 운 좋게도 이미 wp_localize_script
함수를 사용했으므로 여기에 다른 키를 추가하면 됩니다.
wp_localize_script( 'report-a-bug', 'settings', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ), 'send_label' => __( 'Send report', 'reportabug' ) ) );
모든 변수를 준비했으므로 AJAX 호출을 생성해 보겠습니다. 사용자가 버튼을 두 번째 클릭하면 보낼 것입니다.
$( '.report-a-bug' ).on( 'click', '.send-report', function( event ) { var $button = $( this ); $button.width( $button.width() ).text('...'); // set ajax data var data = { 'action' : 'send_bug_report', 'post_id': $button.data( 'post_id' ), 'report' : $( '.report-a-bug-message' ).val() }; $.post( settings.ajaxurl, data, function( response ) { console.log( 'ok' ); } ); } );
이전에 버튼을 켠 클래스의 클릭을 수신합니다.
보시다시피 버튼 텍스트를 "..."로 변경하고 있습니다. 왜죠? 사용자에게 어떤 일이 일어나고 있음을 보여주는 것이 좋은 습관이기 때문입니다. AJAX 요청은 서버 성능에 따라 달라지며 시간이 걸립니다. 30ms일 수도 있지만 3초일 수도 있습니다. 버튼을 클릭한 후 효과가 없는 것 같으면 버튼을 두 번째로 클릭할 가능성이 큽니다. 아시다시피 비동기식이므로 요청이 복제됩니다.
다음으로 data
개체를 생성하겠습니다. 여기에는 서버 콜백으로 보낼 모든 변수가 포함됩니다. WordPress admin-ajax.php
파일에는 action 속성이 필요합니다. 다른 플러그인이 요청을 처리하도록 하지 않는 한 고유해야 합니다. 나머지 매개변수는 선택 사항입니다. textarea
에서 게시물 ID와 보고서 메시지를 보내고 있습니다.
그런 다음 $.post
메서드를 호출합니다. 다음으로, 당신은 그것을 추측했습니다. POST 요청을 보내고 있습니다. 약식 방법이지만 더 많은 옵션이 있는 $.ajax
방법도 사용할 수 있습니다. 첫 번째 매개변수로 핸들러 파일 URL을 전달한 다음 매개변수와 성공 콜백 함수를 전달해야 합니다. 이것은 우리가 응답을 처리하는 곳입니다. 지금은 브라우저 콘솔에 간단한 메시지를 보내는 중입니다.

백엔드에서 요청을 처리할 준비가 되었습니다.

워드프레스 액션
admin-ajax.php 에 어떻게 연결하는지 궁금할 것입니다. 물론 행동으로! WordPress에는 두 가지 작업 유형이 있습니다.
wp_ajax_nopriv_{$action} wp_ajax_{$action}
$action
이 있는 곳에서 AJAX 매개변수에 전달된 작업 이름입니다. 우리의 경우 send_bug_report
입니다.
이 작업 중 첫 번째는 로그인하지 않은 사용자에 대해서만 실행됩니다. 두 번째는 로그인한 사용자 만을 위한 것입니다. 따라서 두 가지 모두에 대해 요청을 처리하려면 두 가지를 모두 정의해야 합니다. 이것이 내가 클래스의 생성자에서 한 일입니다.
public function __construct() { add_filter( 'the_content', array( $this, 'report_button' ), 10, 1 ); add_action( 'wp_enqueue_scripts', array( $this, 'scripts' ) ); add_action( 'wp_ajax_nopriv_send_bug_report', array( $this, 'send_bug_report' ) ); add_action( 'wp_ajax_send_bug_report', array( $this, 'send_bug_report' ) ); }
콜백에서 게시물 제목을 받고 이메일을 보냅니다.
function send_bug_report() { $data = $_POST; $post_title = get_the_title( intval( $data['post_id'] ) ); wp_mail( '[email protected]', 'Bug report in post: ' . $post_title, $data['report'] ); wp_send_json_success( __( 'Thanks for reporting!', 'reportabug' ) ); }
WordPress에서 AJAX를 처리하는 데 있어 가장 중요한 부분은 JSON으로 인코딩된 출력을 출력하고 죽는 마지막 함수인 wp_send_json_success
입니다. AJAX 성공 콜백으로 응답을 얻는 데 필요한 모든 것입니다. 또한 쌍둥이 형제인 wp_send_json_error
가 있지만 이 부분에 대해서는 나중에 다루겠습니다.
이 함수의 객체에는 두 가지 속성이 있습니다.
- 성공
부울이며 성공 또는 오류 함수라고 부를지 여부에 따라 다릅니다. - 데이터
함수에 대한 매개변수를 제공하는 경우.
그것이 모두 백엔드 측에서 온 것입니다. JS에서 응답을 처리해 보겠습니다.
버튼과 텍스트 영역을 제거하고 이전에 준비한 컨테이너에 서버에서 반환된 메시지를 표시합니다.
$.post(settings.ajaxurl, data, function(response) { // remove button and textarea $button.remove(); $('.report-a-bug-message').remove(); // display success message $('.report-a-bug-response').html( response.data ); });
그리고 그게 다야! 작동 중인 AJAX 호출이 있습니다! 하지만 거기서 멈추지 마세요. 우리의 요청은 안전하지 않으며 확실히 사용자 친화적이지 않습니다. 요청이 필요할 때만 실행되도록 해야 합니다.
보호
목하
nonce는 "한 번 사용되는 숫자"입니다. 입력 문자열에서 생성된 짧은 해시입니다. 요청을 확인하는 데 사용할 수 있습니다. 요청이 실제로 WordPress에서 만들어졌고 아무도 위조하지 않은 경우입니다.
버튼에 다른 데이터 속성을 사용할 것입니다.
$nonce = wp_create_nonce( 'report_a_bug_' . get_the_ID() ); $content .= '<div class="report-a-bug"> <button class="show-form" data-nonce="' . $nonce . '" data-post_>' . __( 'Report a bug', 'reportabug' ) . '</button> <textarea class="report-a-bug-message" placeholder="' . __( 'Describe what\'s wrong...', 'reportabug' ) . '"></textarea> <p class="report-a-bug-response"></p> </div>';
보시다시피 입력 문자열에 게시물 ID를 추가하고 있습니다. AJAX 요청 속성에서 이 ID를 사용할 수 있으므로 더 안전합니다.
이제 AJAX 속성에 nonce를 추가해야 합니다.
// set ajax data var data = { 'action' : 'send_bug_report', 'post_id': $button.data('post_id'), 'nonce' : $button.data('nonce'), 'report' : $('.report-a-bug-message').val() };
이제 WordPress가 제공하는 check_ajax_referer
함수를 사용하여 백엔드에서 유효성을 검사합니다.
function send_bug_report() { $data = $_POST; // check the nonce if ( check_ajax_referer( 'report_a_bug_' . $data['post_id'], 'nonce', false ) == false ) { wp_send_json_error(); } $post_title = get_the_title( intval( $data['post_id'] ) ); wp_mail( '[email protected]', 'Bug report in post: ' . $post_title, sanitize_text_field( $data['report'] ) ); wp_send_json_success( __( 'Thanks for reporting!', 'reportabug' ) ); }
요청을 확인하려면 입력 문자열을 다시 생성해야 하므로 AJAX에서 보낸 post_id
키를 사용하고 있습니다. 두 번째 매개변수는 $_REQUEST array
의 키입니다. 세 번째는 nonce가 일치하지 않는 경우 자동화된 wp_die
를 제어합니다.
나는 그것이 스스로 죽는 것을 원하지 않습니다. 대신 이 함수의 결과를 포착하고 멋진 개체에 JSON 오류를 보냅니다.
이메일 메시지 매개변수에서 sanitize_text_field
함수의 사용을 확인할 수도 있습니다. 이것은 사용자가 유해한 스크립트나 HTML을 보내지 않도록 하기 위한 것입니다.
마지막으로 요청이 성공했는지 확인하기 위해 if 문에서 JS의 AJAX 성공 콜백을 래핑해야 합니다.
$.post(settings.ajaxurl, data, function(response) { if ( response.success == true ) { // remove button and textarea $button.remove(); $('.report-a-bug-message').remove(); // display success message $('.report-a-bug-response').html( response.data ); } });
버튼 보호
AJAX가 호출을 종료하기 전에 사용자가 버튼을 두 번째로 클릭할 수 있다는 것을 알고 있습니다. 그러나 두 번째 클릭을 차단하는 간단한 트릭이 하나 있습니다. 바로 버튼을 비활성화하는 것입니다. 따라서 클릭 후에는 차단하고 응답을 받은 후 차단을 해제하겠습니다.
$('.report-a-bug').on('click', '.send-report', function(event) { var $button = $(this); $button.width( $button.width() ).text('...').prop('disabled', true); // set ajax data var data = {...}; $.post(settings.ajaxurl, data, function(response) { if ( response.success == true ) {...} // enable button $button.prop('disabled', false); }); });
오류 처리
확인
사용자가 빈 메시지를 보내려고 하면 어떻게 됩니까? 그런 이메일로 귀찮게 하고 싶지 않습니다. 유효성 검사 기술을 사용하여 이러한 시도를 차단합시다.
JS에서는 사용자에게 뭔가 잘못되었다는 것을 보여주기 위해 간단한 유효성 검사를 추가할 것입니다. 메시지가 비어 있으면 사용자는 텍스트 영역 주위에 빨간색 테두리를 볼 수 있습니다. 메시지가 있으면 중립 경계를 복원합니다.
$('.report-a-bug').on('click', '.send-report', function(event) { var $button = $(this); // check if message is not empty if ( $( '.report-a-bug-message' ).val().length === 0 ) { $( '.report-a-bug-message' ).css( 'border', '1px solid red' ); return false; } else { $( '.report-a-bug-message' ).css( 'border', '1px solid rgba(51, 51, 51, 0.1)' ); } // ... ajax });
WordPress 작업에서 오류 확인
이메일을 보내는 데 문제가 있을 수도 있습니다. wp_mail
함수의 결과를 확인하지 않으면 이메일이 전송되지 않았더라도 사용자에게 성공 메시지가 표시됩니다.
이것을 처리합시다:
function send_bug_report() { $data = $_POST; // check the nonce if ( check_ajax_referer( 'report_a_bug_' . $data['post_id'], 'nonce', false ) == false ) { wp_send_json_error(); } $post_title = get_the_title( intval( $data['post_id'] ) ); $result = wp_mail( '[email protected]', 'Bug report in post: ' . $post_title, sanitize_text_field( $data['report'] ) ); if ( $result == false ) { wp_send_json_success( __( 'Thanks for reporting!', 'reportabug' ) ); } else { wp_send_json_error(); } }
보시다시피 wp_send_json_error
함수를 두 번 사용했지만 사용자에게 고유한 메시지를 표시할 필요가 없습니다. 대신 정확한 오류 설명을 전달하여 두 오류를 모두 포함하는 스크립트 설정 개체에 다른 키를 추가하겠습니다.
// set variables for script wp_localize_script( 'report-a-bug', 'settings', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ), 'send_label' => __( 'Send report', 'reportabug' ), 'error' => __( 'Sorry, something went wrong. Please try again', 'reportabug' ) ) );
남은 일은 사용자에게 오류를 표시하는 것뿐입니다.
$.post( settings.ajaxurl, data, function( response ) { if ( response.success == true ) { // remove button and textarea $button.remove(); $( '.report-a-bug-message' ).remove(); // display success message $( '.report-a-bug-response' ).html( response.data ); } else { // display error message $( '.report-a-bug-response' ).html( settings.error ); } // enable button and revert label $button.text( settings.send_label ).prop( 'disabled', false ); } );
완전한 예
해냈어! AJAX 요청이 완료되었습니다. 보안이 잘 되어 있고 사용자 친화적입니다. 다음은 오류가 발생한 경우 사용자에게 표시되는 내용입니다.

아래에서 전체 플러그인을 다운로드하고 사용자 가이드를 확인할 수 있습니다.
- Github에서 플러그인 다운로드
- Wordpress.org에서 플러그인 다운로드
- 사용자 가이드로 이동
이것이 "페이지 새로 고침 없음" 솔루션을 위한 좋은 기반이 되기를 바랍니다. 웹사이트의 모든 양식에 대해 이 작업을 수행할 수 있습니다. 또한 드롭다운에 있는 많은 제품 목록과 같이 즉시 로드할 필요가 없는 웹 사이트의 무거운 부분을 최적화하는 좋은 방법입니다. 드롭다운 을 클릭한 직후 AJAX를 통해 로드할 수 있습니다. 매우 간단합니다.
가능성은 거의 무한합니다. 당신의 아이디어가 무엇인지 댓글로 알려주세요!