Sayfayı Yeniden Yüklemeden Form Gönderme: WordPress'te AJAX Uygulaması

Yayınlanan: 2022-03-10
Kısa özet ↬ Piyasada birçok "sayfa yenilemesiz" çözüm var, ancak işte AJAX ile oluşturabileceğiniz bir çözüm. Bu öğreticide, okuyucuların sayfayı yeniden yüklemeden rapor göndermesine olanak tanıyan basit bir eklentinin nasıl oluşturulacağını öğrenebilirsiniz.

Sayfayı 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.

Hata raporu gönderme işlemi
Bir kullanıcı bir hatayla karşılaşır ve “Hata Bildir” düğmesini tıklar. Sonuç olarak, bir mesaj için form sunulur. Düğmeye ikinci kez tıklamak, kullanıcıyı yöneticiye gönderecektir.

Yazının sonunda çalışan örneği indirebilir ve kodu tam olarak inceleyebilirsiniz.

Hadi kazalım!

Atlamadan sonra daha fazlası! Aşağıdan okumaya devam edin ↓

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:

Hata bildir düğmesi
'Hata bildir' düğmesi

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:

Tıklandığında Textarea açılır menüsü
tıklamada 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.

AJAX isteğini arka uca gönderme
AJAX isteğini arka uca gönderme

İ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:

Tamamlanmış örnek, doğrulamalı AJAX isteği
Tamamlanmış örnek, doğrulamalı AJAX isteği

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!