تمنح تقنيّة Ajax مواقع الويب إمكانيّةَ تحميل محتوى إلى عناصر مختلفة ضمن الصّفحة دون الحاجة لإنعاش Refresh الصّفحة. قد لا تبدو - للوهلة الأولى - ميزةً مؤثّرة، إلّا أنّها تمكّن من فعل الكثير من الأمور.
تستخدم الكثير من الإجراءات مثل التّصويت، إبداء الإعجاب، التّعليقات على Disqus والتّغريدات على تويتر؛ وإجراءات أخرى كثيرة Ajax للحصول على تجربة مستخدم User experience لا مثيل لها.
ذاع صيت Ajax سنة 2005 عندما استخدمته Google في ميزة اقتراحات البحث، الّتي تُظهر اقتراحات أثناء الكتابة على محرّك بحث Google. لم تكن هذه الميزة لترى النّور لولا وجود تقنيّة Ajax.
سنعرض في هذا المقال لكيفيّة استخدام Ajax في ووردبريس. سيكون الأمر أكثر تعقيدًا قليلًا ممّا تعوّدت عليه، إلّا أنّ الأمور ستجري على ما يُرام إن كان لديك فهم جيّد CSS، HTML وPHP؛ إضافةً لفهم لأساسيّات Javascript.
كيف يعمل Ajax
ليس Ajax في الواقع سوى Javascript. تأتي كلمة Ajax اختصارًا لAsynchronous Javascript And XML (أي: Javascript وXML لا تزامنيّان). تهدف تقنيّة Ajax إلى أن تكون جسرًا بين موقع الويب والخادوم، وهو ما يعني أنّك ستسخدمها بالتّزامن مع Javascript، CSS، HTML وربّما PHP أيضًا؛ الأمر الّذي قد يعقّد الأمور قليلًا.
يعدّ الكائن XMLHttpRequest
الّذي يتبادل البيانات مع الخادوم الأساس الّذي تقوم عليه تقنيّة Ajax. يشبه عمل Ajax عمومًا إرسال استمارة في صفحة ويب. في ما يلي الخطوات الأساسيّة:
- تحدّد البيانات الّتي تريد إرسالها
- تضبُط نداء Ajax
- تستخدم كائن
XMLHttpRequest
لإرسال البيانات إلى الخادوم - تحصُل على إجابة من الخادوم. يُمكن استخدام ردّ الخادوم ضمن شفرة Javascript.
يكثُر استخدام Ajax عبر دوالّ التّغليف Wrapper functions في jQuery، لذا سنركّز على هذه الطّريقة في هذا المقال.
أوّل نداء Ajax
سنحتاج قبل البدء في كتابة شفرة Ajax إلى قالب يُمكن التّعديل عليه، قالب فرعيّ أو إضافة. أنصح باستخدام إضافة. إنشاء إضافة سهل: أنشئ مجلَّدًا فرعيًّا ضمن wp-content/plugins
(اخترتُ اسم ajax-text
). أنشئ ملفّ PHP ضمن المجلَّد وأعطِه نفس اسم المجلَّد (ajax-text.php
) وألصِق الشفرة التّاليّة في الملفّ:
<?php /** * Plugin Name: Ajax Test * Plugin URI: <a href="http://danielpataki.com">http://danielpataki.com</a> * Description: This is a plugin that allows us to test Ajax functionality in WordPress * Version: 1.0.0 * Author: Daniel Pataki * Author URI: <a href="http://danielpataki.com">http://danielpataki.com</a> * License: GPL2 */
ستظهر الإضافة، بعد حفظ الملفّ، في ركن الإضافات في لوحة التّحكّم بووردبريس. فعّلها. للمزيد حول تطوير إضافات ووردبريس راجع دليل مدخل إلى برمجة إضافات ووردبريس.
1- صفّ Enqueueing ملفّ Javascript
سنحتاج لماستخدام ملفّ JavaScript في الإضافة، لذا سنصُفّ الملفّ. نستخدم الشّفرة التّاليّة لهذا الغرض:
add_action( 'wp_enqueue_scripts', 'ajax_test_enqueue_scripts' ); function ajax_test_enqueue_scripts() { wp_enqueue_script( 'test', plugins_url( '/test.js', __FILE__ ), array('jquery'), '1.0', true ); }
تُضيف الشّفرة أعلاه ملفّ test.js
إلى الموقع. أخبرنا ووردبريس أنّ jQuery اعتماديّة يجب تحميلها في التّذييل Footer.
الخطوة التّاليّة هي إنشاء نداء Ajax بسيط داخل ملفّ Javascript.
2- إنشاء نداء Ajax
يحوي نداء Ajax على العديد من المعطيات، سنتعرّف على الأساسيّة منها.
jQuery(document).ready( function($) { $.ajax({ url: "http://yourwebsite.com", success: function( data ) { alert('يبلُغ عدد عناصر div في الصّفحة الرّئيسيّة لديك:' + $(data).find('div').length); } }) })
كلّ ما فعلناه هو استخدام دالّة ()ajax.$
وتحديد بعض الخيّارات. يحدّد المُعطى url
لنداء Ajax أين يجب أن يُرسل الطّلب الّذي تستقبل الدّالةُ الموجودة في المعطى success
الإجابةَ عليه.
يجب أن يُحيل المُعطى url
إلى رابط الصّفحة الرّئيسيّة لموقعك. ستظهر لك، إذا نفّذت الخطوات بطريقة صحيحة، نافذةٌ منبثقة بعدد عناصر div
الموجودة في الصّفحة الرئيسيّة فورَ إنعاش الصّفحة (ﻷخذ التّغييرات على الإضافة في الحسبان).
لا يبدو المظهر أنيقًا؛ إلّا أنّ ما فعلناه في الواقع هو تحميل صفحة مختلفة تمامًا دون إعادة تحميل تلك الّتي نوجد فيها.
مثال كامل لاستخدام Ajax في ووردبريس
يوفّر ووردبريس دعمًا أكبر للمساعدة في استخدام نداءات Ajax ويقدّم آليّة معياريّة لتأديّتها. سنُبدِل عنوان url
بآخر أكثر ديناميكيّة وننشئ طريقةً أفضل للتّخاطب مع الخادوم. سنعرض في المثال التّالي كيفيّةَ إضافة ميزة “أعجبني هذا المقال” إلى موقعنا.
أنشأتُ إضافةً جديدة لهذا الغرض باسم “post-love”، يمكن الملفّ المضغوط للإضافة في آخر الدّرس.
ملحوظة: يجب تعطيل وحذف الإضافة السّابقة ajax-text
حتى يمكن للإضافة الجديدة post-love
العمل بطريقة صحيحة.
1- تخزين وعرض البيانات
سنستخدم حقلًا مُخصَّصًا Custom field لحفظ عدد الإعجابات الّتي تلقّاها المنشور. سنسمّي هذا الحقل post_love
وسنعرض قيمته تحت كلّ مقال في صفحة منفردة Single page. في ما يلي كيفيّة ذلك (ملفّ content-filter.php
):
add_filter( 'the_content', 'post_love_display', 99 ); function post_love_display( $content ) { $love_text = ''; if ( is_single() ) { $love = get_post_meta( get_the_ID(), 'post_love', true ); $love = ( empty( $love ) ) ? 0 : $love; $love_text = '<p class="love-received"><a class="love-button" href="#" data-id="' . get_the_ID() . '">أبدِ(ي) إعجابك</a><span id="love-count">' . $love . '</span></p>'; } return $content . $love_text; }
يمكننا عبر استخدام content-filter.php
عرض أيّ شيء نُريده أسفل محتوى المقال مباشرةً. نستخدم دالّة ()is_singl
للتّأكّد من أنّ الإعجابات تظهر على الصّفحات المنفردة. نحصُل على عدد الإعجابات من الحقل المخصَّص post_love
ونتأكّد من أنّ العدد يساوي صفرًا إن لم توجد إعجابات حتى اللّحظة.
استخدمنا HTML لعرض رابط لإبداء الإعجاب وعدد الإعجابات. نحصُل على معرّف المقال عبر الدّالّة ()get_the_ID
ونمرّره لدالّة get_post_meta
الّتي نحصُل من خلالها على قيمة الحقل المخصَّص post_love
؛ ثمّ في اﻷخير نُرجِع المحتوى متبوعًا بالنّص الّذي أنشأناه للتّو.
نستخدم CSS لإضافة بعض التّحسينات على طريقة العرض عبر صفّ ملفّ CSSكان تفهم جيّدًا على النّحو التّاليّ:
add_action( 'wp_enqueue_scripts', 'post_love_assets' ); function post_love_assets() { if( is_single() ) { wp_enqueue_style( 'love', plugins_url( '/love.css', __FILE__ ) ); }
لاحظ استخدام الشّرط ()is_single
قبل تحميل ملفّ CSS، يعود السّبب في ذلك إلى أنّه لا معنى لتحميل النّمط في صفحات غير منفردة، حيثُ إنّه لا يُستخدَم إلّا فيها؛ الأمر الّذي يُساعد في التّقليل من تأثير الإضافة على زمن تحميل الموقع.
أنشئ ملفّ love.css
في مجلَّد الإضافة وضمّن فيه النّمط التّالي:
.entry-content .love-button { background: #f14864; color: #fff; padding:11px 22px; display:inline-block; border:0px; text-decoration: none; box-shadow: 0px 6px #d2234c; position:relative; } .entry-content .love-button:hover{ top:3px; box-shadow: 0px 3px #d2234c; } .entry-content .love-button:active{ top:6px; box-shadow: none; } #love-count { background: #eee; box-shadow: 0px 6px #ddd; color: #666; padding:11px 22px; display:inline-block; }
تظهر النّتيجة بعد إكمال الخطوات السّابقة على هيئة زرّ بتأثير ثلاثيّ الأبعاد يوجد أمامه عدّاد.
2- نداء Ajax
الخطوة التّاليّة هي تجميع نداء Ajax. يستدعي ذلك كتابة السكربت وصَفَّه. سنناقش، قبل البدْء في كتابة السّكربت، معطَى url
الموجود في نداء Ajax. في المثال السّابق (ajax-text
) كتبنا عنوان الموقع مباشرةً ضمن الشّفرة البرمجيّة، وهي طريقة غير صحيحة أثناء إنشاء الإضافات؛ فكلّ موقع لديه عنوانه الخاصّ.
ملحوظة: سنحذف الشّفرة التّاليّة ونعيد كتابتها من جديد مع إضافة نداء Ajax:
add_action( 'wp_enqueue_scripts', 'post_love_assets' ); function post_love_assets() { if( is_single() ) { wp_enqueue_style( 'love', plugins_url( '/love.css', __FILE__ ) ); }
يوفّر ووردبريس ملفًّا موّحدًا للاستخدام (wp-admin/admin-ajax.php
) ووسائلَ للحصول على مسار الملفّ كامِلًا. يستدعي الملفّ بعض الحيّل أثناء صفّه، نعرض لها في الشّفرة التّاليّة:
add_action( 'wp_enqueue_scripts', 'ajax_test_enqueue_scripts' ); function ajax_test_enqueue_scripts() { if( is_single() ) { wp_enqueue_style( 'love', plugins_url( '/love.css', __FILE__ ) ); } wp_enqueue_script( 'love', plugins_url( '/love.js', __FILE__ ), array('jquery'), '1.0', true ); wp_localize_script( 'love', 'postlove', array( 'ajax_url' => admin_url( 'admin-ajax.php' ) )); }
تُسجّل الشّفرة أعلاه ملفّ Javascript بالطّريقة المُعتادة، ثمّ تمرّر سلسلة محارف String إلى السّكربت عبر الدّالّة ()wp_localize_script
(تُستخدَم هذه الدّالّة عادةً لترجمة سلاسل المحارف الموجودة في Javascript). يُمكنك إضافة سلاسل محارف إلى المصفوفة Array بحسب حاجتك.
يمكننا الآن استخدام المتغيّر postlove.ajax_url
في ملفّ love.js
للحصول على مسار admin-ajax.php
، على النّحو التّاليّ:
jQuery( document ).on( 'click', '.love-button', function() { var post_id = jQuery(this).data('id'); jQuery.ajax({ url : postlove.ajax_url, type : 'post', data : { action : 'post_love_add_love', post_id : post_id }, success : function( response ) { alert(response) } }); })
ليست هذه النّسخةَ النّهائيّة، لكنّنا وضعنا أساس التّخاطب مع الخادوم. ننفّذ دالّة في كلّ مرة يُضغَط فيها على الزّرّ أبد(ي) إعجابك
، ثمّ نأخذ معرّف المقال ونخزّنه في المتغيّر post_id
. يُنشئ سكربت love.js
نداء Ajax يأخذ في معطى url
قيمةَ المتغيّر postlove.ajax_url
. بالنّسبة لمعطى type
فقد أعطيناه القيمة post
أيّ أنّ التّخاطب مع الخادوم سيكون عبر طلبات Post وهي ما يعني أنّنا سنستخدِم المتغيّر POST_$
، من جانب الخادوم، للحصول على البيانات.
توجد في قسم data
كلّ المعطيات الّتي تودّ إرسالها. نحتاج لإرسال معرّف المقال (post_id
) لنعرِف المقال الّذي أبدى الزّائر إعجابه به. يطلُب ووردبريس تحديد إجراء Action عند استخدام الملفّ admin-ajax.php
. حدّدنا الإجراء post_love_add_love
.
أخيرًا نعرض النّتيجة في نافذة منبثقة.
إذا جربّت التّعديلات الجديدة وضغط على زرّ إبداء الإعجاب فستظهر رسالة منبثقة تحوي عدد مرّات إبداء الإعجاب (0
).
لم نعرّف خطّافًا Hook للإجراء post_love_add_love
في الشّفرة أعلاه وهو ما يؤدّي بadmin-ajax
إلى إرجاع القيمة 0
. سنعرّف في الفقرة المواليّة الخطّاف النّاقص.
3- المعالجة من جانب الخادوم
وصلنا في هذه المرحلة إلى إرسال بيانات إلى الخادوم دون أن نخبره مالّذي يجب عليه فعله بها. يجب، عند الضّغط على الزّرّ، زيّادة عدد الإعجابات ب1
وإرجاع القيمة الجديدة. سنحتاج لإنشاء خطّافَين لهذا الغرض.
add_action( 'wp_ajax_nopriv_post_love_add_love', 'post_love_add_love' ); add_action( 'wp_ajax_post_love_add_love', 'post_love_add_love' ); function post_love_add_love() { }
يُنفَّذ الخطّاف الأوّل بالنّسبة للزّوّار الضّيوف، والثّاني لمُسجَّلي الدّخول. بالمناسبة، هذه طريقة جيّدة للتّحكّم في الوصول. الاتّفاق هو كالتّالي:
هل تتذكّر كيف عرّفنا معطى الإجراء في نداء Ajax؟ نحتاج إلى إلحاق هذا المعطى ب_wp_ajax
و/أو _wp_ajax_nopriv
. بالنّسبة للدّالّة يُمكن استخدام أيّ تسميّة، استخدمنا نفس سلسلة المحارف الموجودة في اسم الإجراء للحفاظ على التّجانس. نُضيف الآن وظيفة الزّيّادة بالتّدرّج Incrementing
add_action( 'wp_ajax_nopriv_post_love_add_love', 'post_love_add_love' ); add_action( 'wp_ajax_post_love_add_love', 'post_love_add_love' ); function post_love_add_love() { $love = get_post_meta( $_POST['post_id'], 'post_love', true ); $love++; update_post_meta( $_POST['post_id'], 'post_love', $love ); echo $love; die(); }
نعثُر على القيمة الحاليّة، نزيدها بواحد ثمّ نخزّن القيمة الجديدة ونعرضها. يجب تنفيذ ()die
في نهاية الدّالّة وإلّا فإنّ ملفّ admin-ajax.php
سينفّذ (0)die
الخاصّة به ممّا ينتج عنه عرض 0
إضافيّ في الإجابة.
تظهرعند الضّغط على زر إبداء الإعجاب الآن نافذة منبثقة بها عددُ الإعجابات، وعند إنعاش الصّفحة يظهر العدد إلى جانب الزّرّ المذكور.
لم يتبقّ لنا سوى جعل العدد يتغيّر دون الحاجة لإنعاش الصّفحة. تتكفّل شفرة Javascript التّاليّة بهذه المهمّة:
jQuery( document ).on( 'click', '.love-button', function() { var post_id = jQuery(this).data('id'); jQuery.ajax({ url : postlove.ajax_url, type : 'post', data : { action : 'post_love_add_love', post_id : post_id }, success : function( response ) { jQuery('#love-count').html( response ); } }); })
يؤدّي الضّغط على الزّرّ الآن إلى زيّادة عدد الإعجابات دون الحاجة لإنعاش الصّفحة.
4- لمسات أخيرة
ربّما لاحظت أنّنا أضفنا في زرّ الإعجاب رابطًا إلى #
:
<a class="love-button" href="#" data-id="' . get_the_ID() . '">أبدِ(ي) إعجابك</a>
يعود السّبب في ذلك إلى أخذ الحالة الّتي يكون Javascript فيها غير مفعَّل لدى الزّائر. في هذه الحالة يؤدّي الضّغط على الزّرّ إلى إعادة تنزيل الصّفحة. إلّا أنّ استخدام #
وحده ضمن وسم Tag الرّابط يجعل هذا الأخير غير صالح Invalid. فلنعالج هذا الأمر.
ملحوظة: يُستخدَم ماسك المكان Placeholder #
في خاصيّة href
ضمن وسم <a>
للدّلالة على أنّ الرّابط يُحيل إلى عنصر من الصّفحة يُعطَى معرّفه بعد ماسك المكان (مثلًا:"a href="#id5
). استخدام #
لوحده يعني أنّ الرّابط يُحيل إلى معرّف غير موجود في الصّفحة. في المحصّلة يُحيل الرّابط إلى الصّفحة لكنّه يبقى غير صالح دلاليًّا Semantic.
سنعدّل على الشّفرة بحيث يُحيل الرّابط إلى نداء Ajax، مثلًا: http://yourwebsite.com/wp-admin/admin-ajax.php?action=post_love_add_love&post_id=23
بالنّسبة للزّوّار الّذين يفعّلون Ajax.
add_filter( 'the_content', 'post_love_display', 99 ); function post_love_display( $content ) { $love_text = ''; if ( is_single() ) { $love = get_post_meta( get_the_ID(), 'post_love', true ); $love = ( empty( $love ) ) ? 0 : $love; $love_text = '<p class="love-received"><a class="love-button" href="' . admin_url( 'admin-ajax.php?action=post_love_add_love&post_id=' . get_the_ID() ) . '" data-id="' . get_the_ID() . '">give love</a><span id="love-count">' . $love . '</span></p>'; } return $content . $love_text; }
إذا كان Javascript مفعَّلًا في المتصفّح فيجب تعطيل إمكانيّة تتبّع رابط URL. لذا نُضيف return false
إلى الدّالّة في حدث click
كما يلي:
jQuery( document ).on( 'click', '.love-button', function() { var post_id = jQuery(this).data('id'); jQuery.ajax({ url : postlove.ajax_url, type : 'post', data : { action : 'post_love_add_love', post_id : post_id }, success : function( response ) { jQuery('#love-count').html( response ); } }); // نُرجع القيمة false هنا return false; })
الخطوة الأخيرة هيّ التّفريق بين عمليّات Ajax والعمليّات الأخرى ضمن دالّة ()post_love_add_love
. عند استخدام Ajax نعرض القيمة الجديدة، ثمّ يتوقّف السكربت. إن لم يُستخدَم Ajax (يعني هذا أنّ الزّائر سيُوجَّه إلى admin-ajax
) فكلّ ما نفعله هو إعادة توجيه المتصفّح إلى المقال بعد تنفيذ السّكربت.
في ما يلي النّسخة النّهائيّة لدالّة ()post_love_add_love
:
function post_love_add_love() { $love = get_post_meta( $_REQUEST['post_id'], 'post_love', true ); $love++; update_post_meta( $_REQUEST['post_id'], 'post_love', $love ); if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) { echo $love; die(); } else { wp_redirect( get_permalink( $_REQUEST['post_id'] ) ); exit(); } }
أبدلنا المتغيّر POST_$
بREQUEST_$
إذ أنّ الزوّارّ بAjax مفعَّل سيستخدمون طلب POST
في ما يستخدم بقيّة الزّوّار طلب GET
. يمكّن متغيّر REQUEST_$
من الحصول على البيانات في الحالتيْن.
جوانب إضافية تجب مراعاتها عند استخدام Ajax
Ajax ليس صعبًا، إلّا أنّه يوجد الكثير من الأمور السّهلة الّتي تجب عليك معرفتها. في ما يلي أهمّ جانبيْن ينبغي عليك الاهتمام بهما.
1- الأمان
يُمكن أن تؤدّي قلّة الحذر أثناء استخدام Ajax إلى مشاكل أمنيّة عديدة. لا تتحقّق الإضافة التّي أنشأناها أعلاه من الضّغطات المتعدّدة الّتي يُمكن أن تؤدّي - فضلًا عن تشويه النّتائج - إلى زيّادة الحمل على الخادوم، خصوصًا إن واصل الكثيرون الضّغط على الزّرّ في نفس الوقت. علاوةً على ذلك فإنّ تغيير العدّاد لا يحتاج للضّغط على الزّر؛ مجرّد الدّخول إلى الرّابط (مثلًا http://yourwebsite.com/wp-admin/admin-ajax.php?action=post_love_add_love&post_id=23
) يفي بالمهمّة.
خذ في الحسبان أنّ بعض الإضافات تسمح بحذف المقالات من الواجهة اﻷماميّة دون الحاجة للدّخول إلى لوحة التّحكّم؛ ماذا لو وُجِد رابط تؤدّي زيّارته إلى نفس التّأثير؟ ليست وضعيّة مثاليّة.
استخدام الأرقام الخاصّة Nonces هو إحدى وسائل تأمين الاستمارات والرّوابط ضدّ المحاولات الخبيثة.
2- تجربة المستخدم
يعود انتشار استخدام Ajax إلى أنّ المستخدم يحصُل على تفاعليّة أكبر مع التّقليل من وقت التّحميل. يعني هذا أيضًا أنّه يجب عليك العمل جاهدًا للتّأكّد من أنّ استخدامك لAjax يرفع حقًا من نوعيّة تجربة المستخدم: يجب أن يعرف الزّائر دائمًا مالّذي يحدُث ولماذا. لو كانت إضافة post-love
موجَّهةً للنّشر ﻷضفتُ أيقونة لحالة التّحميل تعطّل زرّ الإعجاب عند الضّغط عليه، ثمّ بعد نجاح العمليّة يعود الزّرّ لحالته الطّبيعيّة. تُمكن إضافة هذه الميزة عن طريق معطى beforeSend
ضمن دالّة ()ajax.$.
يُتيح beforeSend إمكانيّة تنفيذ بعض التّعليمات قبل إرسال البيانات إلى الخادوم.
إضافة إشارة مرئيّة أثناء تغيّر عدد الإعجابات فكرة جيّدة؛ إن لم يكن المستخدم يعرف مالّذي ينتظره عند الّضغط على الزّر فربّما لا يُلاحظ تغيّر عدد الإعجابات.
في المقابل، لا تبالِغ باستخدام التّأثيرات المرئيّة أثناء التّعامل مع نداءات Ajax، كما حصل للكثيرين مع انتشار هذه التّقنيّة فجعلوا كلّ شيء يتحرّك وينشط في كلّ اتّجاه. لا تضف تأثيرات تلفت النّظر إلّا إذا كان لذلك معنى، ولا تجعل المستخدم ينتظر حتّى نهاية التّحريكة Animation؛ وإلّا فإنّ جودة تجربة المستخدم ستنقُص ولن تزيد.
خاتمة
تعدّ تقنيّة Ajax من الأدوات القويّة المتاحة للمطوّرين من أجل إضافة التّفاعليّة والتّقليل من الضّغط على الخادوم. لن يُمكن إحصاء الميزات الممكن تقديمها باستخدام Ajax: عرض التّعليقات دون الحاجة لإعادة تنزيل الصّفحة، التّمرير اللّامتناهيّ Infinite scrolling للمقالات، التّحميل الخامل Lazy-loading للصوّر، وغيرها الكثير.
سيجعل Ajax تطبيقك أفضل بكثير شرطَ الانتباه إلى تفاصيل تجربة المستخدم وعدم استخدامه لغير ضرورة.
رابط تنزيل إضافة `post-love` في صورتها النّهائيّة. post-love.zip
ترجمة بتصرّف لمقال Using AJAX With PHP on Your WordPress Site Without a Plugin لكاتبه Daniel Pataki.
أفضل التعليقات
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.