Sayfayı Yeniden Yüklemeden Form Gönderme: WordPress'te AJAX Uygulaması
Yayınlanan: 2022-03-10Sayfayı yeniden yüklemeden bir form göndermek istediyseniz, kullanıcıya yazarken önerilerde bulunan ileriye dönük bir arama işlevi sağlayın veya belgeleri otomatik olarak kaydedin, o zaman ihtiyacınız olan şey AJAX'tır ( XHR olarak da bilinir). Sunucuya bir sahne arkası isteği gönderilir ve veriler formunuza döndürülür. Sayfada bir işlem yaptıktan sonra bir yükleyici animasyonu gördüğünüzde, muhtemelen sunucuya gönderilen bir AJAX isteğidir.
Bu makalede, AJAX çağrıları oluşturma ve işleme sürecinin tamamında size rehberlik edeceğim. Yalnızca nasıl AJAX araması yapacağınızı değil, aynı zamanda WordPress'in geliştiricilere kutudan çıkar çıkmaz sunduğu özellikleri kullanarak bunu en iyi şekilde nasıl yapacağınızı da öğreneceksiniz. Okuyucuların yöneticiye web sitenizde tespit edebilecekleri herhangi bir hata hakkında bilgi içeren bir rapor göndermelerini sağlayacak basit bir eklenti oluşturacağız.

Yazının sonunda çalışan örneği indirebilir ve kodu tam olarak inceleyebilirsiniz.
Hadi kazalım!
AJAX
“Sayfayı yeniden yüklemeden” buradaki anahtar cümledir. AJAX, Asenkron JavaScript ve XML anlamına gelir, çünkü başlangıçta sunucudan döndürülen verilerin XML'de olması gerekir. Ancak, bunları JavaScript'in daha çok sevdiği JSON'da göndermek daha kolaydır.
Bir e-posta göndermek için AJAX kullanacağız. Bunu ön uçtan yapamazsınız, bu yüzden arka ucu aramanız gerekir. Genellikle, sunucuya bir POST isteği gönderir, bunu halleder ve kullanıcıyı formla sayfaya geri yönlendirirdik. Bu yinelemede, sayfayı yeniden yüklemek istemiyoruz. Bunun yerine, JavaScript ile form verilerini yakalayacağımız ve ardından yanıtı işlemek için sunucuya eşzamansız bir istek göndereceğimiz doğrudan arka ucu çağırıyoruz.
WordPress AJAX'ın çalışması gereken üç şey vardır – beş tanesinin iyi çalışması için. Bunlar:
- AJAX eylemi için nesne
- JavaScript komut dosyası
- WordPress eylemi
- Koruma
- Hata yönetimi
Her birine daha yakından bakalım.
Nesne
Bizim amacımız formdur. Bu, JavaScript ile ele almamız gereken şey. WordPress eklentisinin ihtiyaç duyduğu üstbilgiye sahip bir dosya oluşturup içine boş bir nesne koyarak başladım. Sonunda, eklentinin sınıfının yeni bir örneğini oluşturuyorum.
<?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();
Burada biraz OOP kullanmama rağmen, herhangi bir gelişmiş uygulama kullanmayacağız. Kod, prosedürel olarak ayrı işlevlerle yazıldığında da çalışır. Ancak WordPress eklentilerindeki nesnelerin bir avantajı vardır: İşlevlerinizin önüne eklemeniz gerekmez - yalnızca sınıf adının benzersiz olması gerekir.
Formumuzu kullanıcılara gösterelim. the_content
filtresine bağlanacağız ve formu her gönderinin sonuna yerleştireceğiz. Sınıfın yapıcısında filtreyi ekledim:
public function __construct() { add_filter( 'the_content', array( $this, 'report_button' ), 10, 1 ); }
Ve form HTML ile bir geri arama yöntemi oluşturdu:
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; }
Form, gerekli tüm işaretlemelere sahiptir:
- Formu göstermek ve mesajı göndermek için bir düğme;
-
textarea
; - Yanıt için kapsayıcı (bunu daha sonra kullanacağız).
Düğme, geçerli posta kimliğini depolayan data-post_id
özelliğine sahiptir. Makaleyi tanımlamak için bunu JavaScript'te alacağız.
Sadece bazı temel stillere ihtiyacımız var, bu yüzden wp_enqueue_scripts
eylemi ve ilgili geri arama ile kendi stil sayfamızı kaydedelim:
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' ); }
Stil sayfasının kendisi çok basittir. Tasarımı düzeltmek istiyoruz.
.report-a-bug-message { display: none; margin-top: 1em; } .report-a-bug-response { margin-top: 1em; }
Düğme şu şekilde görünür:

Senaryo
İçine biraz hayat koymak için nesnemiz hazır. Bunu düz JavaScript ile yapmak yerine, WordPress'in varsayılan olarak her sayfada yüklediği jQuery kullanacağız.
Mevcut komut dosyaları yönteminde, wp_enqueue_script
işlevini kullanarak JS dosyasını ekleyeceğim.
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' ) ) ); }
Ayrıca çevrilmiş düğme etiketini JS'ye iletmek için wp_localize_script
işlevini kullanıyorum. JavaScript'te herhangi bir gettext
işlevimiz yok, bu yüzden burada yapmak zorundayız. Bu işlev, doğrudan komut dosyamızdan erişilebilen ayarlar nesnesini yaratacaktır.
Komut dosyamızda, bir düğme tıklamasını dinleyeceğiz. Bu gerçekleştiğinde, textarea
göstereceğiz ve formu gönderen ikinci tıklamayı dinlemek için düğme sınıfını değiştireceğiz.
( 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 );
İşte mevcut ilerleme:

textarea
açılır menüsüAJAX isteğini oluşturmak için en iyi zaman!
WordPress'e AJAX İstekleri
Bir AJAX isteği göndermek için gerçekten yalnızca bir ve yalnızca parametreye ihtiyacınız vardır: istenen URL. WordPress, AJAX için özel dosyaya sahiptir, bu nedenle kendi dosyamızı oluşturmamız gerekmez. Bu /wp-admin/admin-ajax.php
.
wp-admin
alanında olduğumuz sürece, bu dosya URL'si JS'de ajaxurl
değişkeninde mevcuttur. Ön uçta, bu değişkeni kendi başımıza iletmeliyiz. Neyse ki wp_localize_script
işlevini zaten kullandık, bu yüzden ona başka bir anahtar ekleyebiliriz:
wp_localize_script( 'report-a-bug', 'settings', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ), 'send_label' => __( 'Send report', 'reportabug' ) ) );
Tüm değişkenleri hazırladık ve AJAX çağrısını oluşturalım. Kullanıcı düğmeye ikinci kez tıkladığında göndereceğiz.
$( '.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' ); } ); } );
Daha önce butonunu açtığımız sınıfa tık tık dinliyoruz.
Gördüğünüz gibi, düğme metnini “…” olarak değiştiriyorum. Neden? Çünkü kullanıcıya bir şeylerin olduğunu göstermek iyi bir uygulamadır. AJAX istekleri sunucu performansına bağlıdır ve biraz zaman alacaktır. Belki 30ms, ama belki 3 saniye de olabilir. Düğmeye tıkladıktan sonra herhangi bir etki görünmüyorsa, büyük olasılıkla düğme ikinci kez tıklanacaktır. Bu, isteği çoğaltır çünkü artık bildiğiniz gibi bunlar eşzamansızdır.
Sırada, data
nesnesini oluşturuyorum. Bu, sunucu geri çağrısına gönderilecek tüm değişkenleri içerir. WordPress admin-ajax.php
dosyası, action özelliğini gerektirir. Diğer eklentinin isteklerinizi işlemesini istemiyorsanız, bu benzersiz olmalıdır. Parametrelerin geri kalanı isteğe bağlıdır. Mesaj kimliğini ve rapor mesajını textarea
gönderiyorum.
Daha sonra $.post
yöntemini çağırıyoruz. Sonra, tahmin ettiniz; POST isteği gönderiyor. Bu bir steno yöntemidir, ancak daha fazla seçeneğe sahip olan $.ajax
yöntemini de kullanabilirsiniz. İlk parametre olarak, işleyici dosyamızın URL'sini, ardından parametreleri ve ardından başarılı geri arama işlevini iletmeliyiz. Bu, yanıtı ele aldığımız yer. Şimdilik, basit mesajı tarayıcının konsoluna gönderiyoruz.


İsteği arka uçta işlemeye hazırız.
WordPress Eylemi
admin-ajax.php dosyasına nasıl bağlanacağımızı merak ediyor olabilirsiniz. Tabii ki aksiyonla! WordPress'in iki eylem türü vardır:
wp_ajax_nopriv_{$action} wp_ajax_{$action}
$action
olduğu yerde, AJAX paragraflarında geçirilen eylem adı. Bizim durumumuzda send_bug_report
.
Bu eylemlerden ilki, yalnızca oturum açmamış kullanıcılar için yürütülecektir. İkincisi, yalnızca oturum açmış kullanıcılar için. Bu nedenle, isteğin her ikisi için de ele alınmasını istiyorsanız, ikisini de tanımlamanız gerekir. Bu, sınıfın yapıcısında yaptığım şey:
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' ) ); }
Geri aramada, sadece gönderi başlığını alıyorum ve e-postayı gönderiyorum:
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' ) ); }
AJAX'ı WordPress'te işleme açısından en önemli kısım, son işlevdir - JSON kodlu çıktıyı yazdıran ve ölen wp_send_json_success
. AJAX başarılı geri arama ile yanıtı almak için ihtiyacımız olan tek şey. Ayrıca wp_send_json_error
bir ikiz kardeşi vardır, ancak bu kısma daha sonra geleceğiz.
Bu işlevlerdeki nesnenin iki özelliği vardır:
- başarı
Bir booleandır ve ona başarı mı yoksa hata işlevi mi dediğinize bağlıdır. - veri
İşlev için parametre sağlarsanız.
Hepsi arka uç tarafından. JS'deki yanıtı ele alalım.
Buton ve textarea'yı kaldıracağız ve daha önce hazırladığımız kapsayıcıda sunucudan dönen bir mesajı görüntüleyeceğiz:
$.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 ); });
Ve bu kadar! Çalışan AJAX çağrımız var! Ama orada durma. İsteğimiz güvenli değil ve kesinlikle kullanıcı dostu değil. İsteğin yalnızca gerektiğinde yürütüldüğünden emin olmalıyız.
Koruma
Nonce
Nonce, "bir kez kullanılan sayı"dır. Bir girdi dizesinden oluşturulan kısa bir karmadır. İsteği doğrulamak için kullanabiliriz - eğer gerçekten WordPress tarafından yapılmışsa ve kimse onu taklit etmiyorsa.
Düğme için başka bir veri özniteliği kullanacağız:
$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>';
Gördüğünüz gibi, giriş dizesine posta kimliğini ekliyorum. Bu kimliği AJAX istek özelliklerinde kullanacağız, bu yüzden sadece daha güvenli.
Şimdi nonce'yi AJAX özelliklerine eklemeliyiz:
// 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() };
Şimdi WordPress'in sağladığı check_ajax_referer
işlevini kullanarak arka uçta doğrulayacağız:
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' ) ); }
İsteği doğrulamak için giriş dizesini yeniden oluşturmamız gerekiyor, bu yüzden AJAX'tan gönderilen post_id
anahtarını kullanıyorum. İkinci parametre $_REQUEST array
anahtardır. Üçüncüsü, nonce eşleşmiyorsa otomatik wp_die
kontrol eder.
Kendi kendine ölmesini istemiyorum. Bunun yerine, bu işlevin sonucunu yakalıyorum ve güzel bir nesnede JSON hatası gönderiyorum.
E-posta mesajı parametresinde sanitize_text_field
işlevinin kullanıldığını da fark edebilirsiniz. Bu, kullanıcının herhangi bir zararlı komut dosyası veya HTML göndermeyeceğinden emin olmak içindir.
Son olarak, isteğin başarılı olup olmadığını kontrol etmek için AJAX başarı geri aramasını JS'de if ifadesine sarmamız gerekir:
$.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 ); } });
Düğme Koruması
AJAX aramayı bitirmeden önce kullanıcının düğmeyi ikinci kez tıklayabileceğini biliyorsunuz. Ancak ikinci tıklamayı engelleyecek basit bir numara var - düğmeyi devre dışı bırakmak. Bu yüzden, tıklamadan sonra onu engelleyeceğim ve yanıtı aldıktan sonra engelini kaldıracağım:
$('.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); }); });
Hata yönetimi
doğrulama
Kullanıcı boş bir mesaj göndermeye çalışırsa ne olur? Bu tür e-postalarla rahatsız edilmek istemiyorum. Doğrulama teknikleri ile bu girişimleri engelleyelim.
JS'de kullanıcıya bir şeylerin yanlış gittiğini göstermek için basit bir doğrulama ekleyeceğim. Mesaj boşsa, kullanıcı metin alanının etrafındaki kırmızı kenarlığı görecektir. Orada bir mesaj varsa, tarafsız sınıra geri dönüyoruz:
$('.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 Eyleminde Hataları Kontrol Etme
E-postayı gönderirken de sorun yaşayabiliriz. wp_mail
fonksiyonunun sonucunu kontrol etmezsek, e-posta gönderilmemesine rağmen kullanıcı bir başarı mesajı alacaktır.
Şunu halledelim:
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(); } }
Gördüğünüz gibi wp_send_json_error
işlevini iki kez kullandık, ancak kullanıcılar için benzersiz mesajlar görüntülemeye gerek yok. Bunun yerine, tam hata açıklamasını geçerek, komut dosyası ayarları nesnemize her iki hatayı da kapsayacak başka bir anahtar ekleyeceğim:
// 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' ) ) );
Yapılması gereken tek şey hatayı kullanıcıya göstermektir:
$.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 ); } );
Tam Örnek
Yaptık! AJAX talebimiz yapılmıştır; iyi güvenlidir ve kullanıcı dostudur. Herhangi bir hata durumunda kullanıcının göreceği şey budur:

Aşağıdan eklentinin tamamını indirebilir ve kullanım kılavuzlarını inceleyebilirsiniz:
- Eklentiyi Github'dan indirin
- Eklentiyi Wordpress.org'dan indirin
- Kullanım kılavuzlarına gidin
Umarım bu size kendi "sayfa yenilemesiz" çözümleriniz için güzel bir temel sağlar. Bunu web sitenizdeki tüm formlara yapabilirsiniz. Ayrıca, açılır menüdeki büyük bir ürün listesi gibi, hemen yüklenmesi gerekmeyen web sitesinin herhangi bir ağır parçasını optimize etmenin harika bir yoludur. Bunları açılır listeye tıkladıktan hemen sonra AJAX aracılığıyla yükleyebilirsiniz - bu kadar basit.
Olasılıklar neredeyse sınırsız. Fikirlerinizin ne olduğunu yorumlarda bana bildirin!