إرسال النماذج دون إعادة تحميل الصفحة: تطبيق AJAX في WordPress

نشرت: 2022-03-10
ملخص سريع ↬ هناك الكثير من الحلول "بدون تحديث الصفحة" ، ولكن إليك أحد الحلول التي يمكنك إنشاؤها باستخدام AJAX. في هذا البرنامج التعليمي ، يمكنك معرفة كيفية إنشاء مكون إضافي بسيط يسمح للقراء بإرسال تقرير دون إعادة تحميل الصفحة.

إذا كنت ترغب في أي وقت مضى في إرسال نموذج دون إعادة تحميل الصفحة ، فقم بتوفير وظيفة البحث الفوري التي تطالب المستخدم باقتراحات أثناء الكتابة ، أو حفظ المستندات تلقائيًا ، فما تحتاج إليه هو AJAX (المعروف أيضًا باسم XHR ). يتم إرسال طلب من وراء الكواليس إلى الخادم ، وإعادة البيانات إلى النموذج الخاص بك. عندما ترى رسمًا متحركًا محملًا بعد قيامك ببعض الإجراءات على الصفحة ، فمن المحتمل أن يكون طلب AJAX يتم إرساله إلى الخادم.

في هذه المقالة ، سأوجهك خلال العملية الكاملة لإنشاء مكالمات AJAX والتعامل معها. لن تتعلم كيفية إجراء مكالمة AJAX فحسب ، بل ستتعلم أيضًا كيفية القيام بذلك بأفضل طريقة باستخدام الميزات التي يقدمها WordPress للمطورين فورًا. سننشئ مكونًا إضافيًا بسيطًا سيسمح للقراء بإرسال تقرير إلى المسؤول مع معلومات حول أي خطأ قد يكتشفونه على موقع الويب الخاص بك.

عملية تقديم تقرير الخطأ
يصادف المستخدم خطأ وينقر على زر "الإبلاغ عن خطأ". نتيجة لذلك ، يتم تقديم نموذج الرسالة. سيؤدي النقر فوق الزر مرة ثانية إلى إرسال المستخدم إلى المسؤول.

في نهاية المقالة ، يمكنك تنزيل مثال العمل وفحص الكود بالكامل.

دعونا نحفر!

المزيد بعد القفز! أكمل القراءة أدناه ↓

أجاكس

"بدون إعادة تحميل الصفحة" هي الجملة الرئيسية هنا. AJAX تعني Asynchronous JavaScript و XML لأنه في البداية ، من المفترض أن تكون البيانات التي يتم إرجاعها من الخادم بتنسيق XML. ومع ذلك ، من الأسهل إرسالها بتنسيق 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 .
  • حاوية للاستجابة (سنستخدم هذا لاحقًا).

يحتوي الزر على السمة 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 عادي ، سنستخدم jQuery الذي يقوم WordPress بتحميله افتراضيًا في كل صفحة.

في طريقة البرامج النصية الحالية ، سأضيف ملف JS باستخدام وظيفة wp_enqueue_script .

 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' ) ) ); }

أنا أستخدم أيضًا وظيفة wp_localize_script لتمرير تسمية الزر المترجمة إلى JS. ليس لدينا أي وظائف gettext في JavaScript ، لذلك علينا القيام بذلك هنا. ستنشئ هذه الوظيفة كائن الإعدادات الذي يمكن الوصول إليه مباشرة من البرنامج النصي الخاص بنا.

في البرنامج النصي الخاص بنا ، سنستمع إلى نقرة زر. بمجرد حدوث ذلك ، سنعرض منطقة 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 القائمة المنسدلة عند النقر
textarea المنسدلة عند النقر

إنه أفضل وقت لإنشاء طلب 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 على أداء الخادم وستستغرق بعض الوقت. ربما 30 مللي ثانية ، لكن ربما 3 ثوانٍ أيضًا. إذا بدا أنه لم يكن هناك أي تأثير بعد النقر فوق الزر ، فمن المرجح أن يتم النقر فوق الزر مرة أخرى. سيؤدي هذا إلى تكرار الطلب لأنه كما تعلم الآن ، هذه غير متزامنة.

بعد ذلك ، أقوم بإنشاء كائن data . هذا يحتوي على جميع المتغيرات التي سيتم إرسالها إلى رد الاتصال الخادم. يتطلب ملف WordPress admin-ajax.php خاصية الإجراء. يجب أن يكون هذا فريدًا إلا إذا كنت تريد أن يتعامل المكون الإضافي الآخر مع طلباتك. باقي المعلمات اختياري. أنا أرسل معرف المنشور ورسالة التقرير من textarea .

ثم نقوم باستدعاء طريقة $.post . بعد ذلك ، خمنت ذلك ؛ إنه يرسل طلب POST. إنها طريقة مختصرة ، ولكن يمكنك أيضًا استخدام طريقة $.ajax ، والتي تحتوي على المزيد من الخيارات. كمعامل أول ، يتعين علينا تمرير عنوان URL الخاص بملف المعالج ، ثم المعلمات ثم وظيفة رد الاتصال الناجحة. هذا هو المكان الذي نتعامل فيه مع الاستجابة. في الوقت الحالي ، نقوم فقط بإرسال رسالة بسيطة إلى وحدة تحكم المتصفح.

إرسال طلب AJAX إلى النهاية الخلفية
إرسال طلب AJAX إلى النهاية الخلفية

نحن على استعداد للتعامل مع الطلب في النهاية الخلفية.

عمل ووردبريس

قد تتساءل عن كيفية ربطنا بالملف 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' ) ); }

الجزء الأكثر أهمية فيما يتعلق بمعالجة AJAX في WordPress هو الوظيفة الأخيرة - wp_send_json_success التي تطبع إخراج JSON المشفر وتموت. كل ما نحتاجه للحصول على الاستجابة من خلال رد اتصال نجاح 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 ); });

وهذا كل شيء! لدينا مكالمة أجاكس العاملة! لكن لا تتوقف عند هذا الحد. طلبنا ليس آمنًا وبالتأكيد ليس سهل الاستخدام. علينا التأكد من تنفيذ الطلب فقط عندما يتعين عليه ذلك.

حماية

نونس

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>';

كما ترى ، أقوم بإضافة معرف المنشور إلى سلسلة الإدخال. سيكون لدينا هذا المعرف متاحًا في خصائص طلب AJAX ، لذلك فهو أكثر أمانًا.

الآن علينا إضافة nonce إلى خصائص AJAX:

 // 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() };

سنقوم الآن بالتحقق من صحتها في الواجهة الخلفية باستخدام وظيفة check_ajax_referer ، التي يوفرها WordPress:

 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' ) ); }

للتحقق من صحة الطلب ، يتعين علينا إعادة إنشاء سلسلة الإدخال ، لذلك أنا أستخدم المفتاح post_id المرسل من AJAX. المعلمة الثانية هي المفتاح في $_REQUEST array . الثالث يتحكم في wp_die الآلي إذا لم يكن nonce مطابقًا.

لا أريدها أن تموت نفسها. بدلاً من ذلك ، ألاحظ نتيجة هذه الوظيفة وأرسل خطأ JSON في كائن جميل.

قد تلاحظ أيضًا استخدام وظيفة sanitize_text_field في معلمة رسالة البريد الإلكتروني. هذا فقط للتأكد من أن المستخدم لن يرسل أي نصوص أو HTML ضارة.

أخيرًا ، نحتاج إلى التفاف رد اتصال نجاح AJAX في JS في عبارة if للتحقق مما إذا كان الطلب ناجحًا:

 $.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 الخاص بنا ؛ إنه مؤمن جيدًا وسهل الاستخدام. هذا ما سيراه المستخدم في حالة وجود أي أخطاء:

مثال منتهي ، طلب AJAX مع التحقق من الصحة
مثال منتهي ، طلب AJAX مع التحقق من الصحة

يمكنك أدناه تنزيل المكون الإضافي الكامل والتحقق من أدلة المستخدم:

  • قم بتنزيل البرنامج المساعد على Github
  • قم بتنزيل البرنامج المساعد من Wordpress.org
  • انتقل إلى أدلة المستخدم

آمل أن يمنحك هذا أساسًا جيدًا لحلولك "بدون تحديث الصفحة". يمكنك القيام بذلك لجميع النماذج الموجودة على موقع الويب الخاص بك. إنها أيضًا طريقة رائعة لتحسين أي جزء ثقيل من موقع الويب لا يلزم تحميله على الفور ، مثل قائمة كبيرة من المنتجات في قائمة منسدلة. يمكنك تحميلها عبر AJAX بعد النقر على القائمة المنسدلة - الأمر بهذه البساطة.

الاحتمالات لا حدود لها تقريبا. اسمحوا لي أن أعرف في التعليقات ما هي أفكارك!