بسم الله الرحمن الرحيم والصلاة والسلام على سيدنا محمد وعلى اله وصحبه أجمعين
لاحظ كثرة الاستفسارات في عدة منتديات حول موضوع لو كان عندي قائمتين منسدلة select list كيف أغير مثلا ً محتويات القائمة الثانية عندما يحدد المستخدم عنصر معين في القائمة الأولى ، ومثال على ذلك هو الدول والمدن ، أي عندما يختار المستخدم دولة معينة تتغير محتويات المدن إلى مدن الدولة التي حددها المستخدم ، والأمثلة كثيرة على هذا الأمر .
[ مثال مباشر على الدرس اضغط هنا ]
الموضوع بسيط جدا ً فقط محتاج قليل من التركيز .
الامر لايمكن حصره على مثال معين او طريقة معينة الامثلة كثيره وكذلك ربما قد لا نتحتاج لاستخدام قواعد بيانات مثل MySQL ملف XML قد يفي بالغرض او حتى ملف txt لكن حتى تتضح الصورة اكثر بالنسبة للمبتدئين اخترت ان اعمل المثال على قاعدة بيانات MySQL ، ويمكن للشخص اختيار ما يناسبه ولا يقتصر الموضوع على طريقة واحدة .
في البداية وقبل كتابة أي أوامر برمجية نحتاج نحلل الموضوع ونفهم الفكرة كيف سوف تتم لان الاكواد قد تختلف من شخص إلى أخر لكن الفكرة واحدة.
سأبدأ أولا ً بتحليل قاعدة البيانات كيف سوف تكون ، رغم أنها بسيطة جدا ً لكن زيادة لزيادة الفهم أكثر وتفصيل الأمور .
العناصر الأساسية في هذا الموضوع هما عنصرين قد يزيدوا لكن في هذا الدرس سأفترض أنهم عنصرين فقط تسهيلا ً للفهم وسآخذ مثال الدول والمدن.
العنصر الأول مثلا ً وليكن هو الدولة countries والعنصر الثاني هي المدينة Cities، إذن سيكون لدي هناك جدول للدول وجدول أخر للمدن , نأخذ أولا ً جدول الدول وسأضع فيه ثلاثة حقول فقط هما رقم الدولة ID وكذلك اسم الدولة name و القيمة value هذه سنستخدمها مع الوسم select بإمكانك أن تضع حقول أكثر حسب رغبتك ، أما في جدول المدن سأضع اربعة حقول الأول رقم المدينة ID والثاني اسم المدينة name والثالث value والرابع countrie_id عبارة عن foreign key من جدول الدول لعمل العلاقة مابين جدول الدول وجدول المدن .
سيكون المخطط البياني للجداول بالشكل التالي :

هذا هو المخطط البسيط للجدولين وهذا مثال أخر لبعض السجلات في الجدولين :

حسنا ً اعتقد أن الفكرة اتضحت الآن بالنسبة لتخطيط قاعدة البيانات , سننتقل إذن إلى تحليل آلية العمل .
سنحتاج إلى ملفين PHP الملف الأول نسميه form.php والملف الثانية Cities.php ايضا ً ننشى مجلد للملفات المؤقته بأسم tempCities كذلك لا ننسى مكتبة jQuery
- في البداية عند فتح الصفحة ينفذ استعلام على قاعدة البيانات لجلب الدول ووضعها في قائمة منسدلة مثلا ً لنسمي هذه القائمة بـ list1 ، ثم ينفذ استعلام آخر لجلب المدن المتعلقة بالدولة المحددة حاليا ً في list1 ثم يضعها في قائمة منسدلة أخرى ولنسميها list2 ، هذه الخطوة الأولى وهي الافتراضية عند دخول المستخدم إلى الموقع للمرة الأولى .
- الخطوة الثانية وهي عندما يقوم المستخدم باختيار عنصر من list1 تتغير القيم في list2 .
- سأضيف خطوة أخرى اختياريه لإضافة مزيد من المرونة ، وهي أن الاستعلام في قاعدة البيانات ينفذ مره واحده فقط ثم يتم حفظ القيم في ملف مؤقت على الخادم Server وفي المرة الثانية يتم اخذ البيانات من الملف المؤقت وليس من قاعدة البيانات ، هذا الأمر سيعطي أولا ً سرعة اكبر في جلب البيانات وثانيا ً سيخفف الضغط على الخادم.
حسنا ً بعد أن حللنا قاعدة البيانات وتصورنا آلية العمل نبدأ الآن بالتطبيق العملي باستخدام التقنيات التي ستساعدنا في هذه العملية .
نأخذ أول خطوة وهي كتابة الهيكلة الأساسية لكودHTML في ملف form.php :
<html> <head> <title>Change List</title> </head> <body> <form method="POST" action="#"> <select name="list1" id="Countries"> </select> <select name="list2" id="Cities"> </select> <input type="submit" value="go" /> <form> <div id="loading" style="display:none">Loading</div> </body> </html>
لاحظ الكود بسيط جدا ً سأوضح ابرز الأمور فقط .
أنشأت نموذج بداخلة قائمتين منسدلة الأولى اسمها list1 والثانية list2 بالإضافة إلى id لكل قائمة هذا الـ id فائدته ستتضح فيما بعد ، لاحظ أنني لم أضع أي خيارات على القائمة والسبب آن هذه الخيارات سيتم جلبها من قاعدة البيانات، أيضا ً أضفت div بداخله نص لكنه غير ظاهر يظهر فقط في فترة تغيير القائمة , هذا الأمر اختياري فقط لإضافة بعض الجماليات بإمكانك الاستغناء عنه ، وسيتضح هذا الأمر لنا في السطور القادمة .
حسنا ً الخطوة التالية وهي جلب أسماء الدول ووضعها في list1 ، عن طريق الكود التالي :
<select name="list1" id="Countries">
<?php
$query = mysql_query("SELECT id,name,value FROM countries");
while($rows = mysql_fetch_array($query))
{
echo '<option value="'.$rows['value'].'">'.$rows['name'].'</option>';
}
?>
</select>إلى هنا اعتقد انه لا جديد الاكواد مألوفة للكل ، نتقل الآن إلى الخطوة الأهم في هذا الموضوع وهي القائمة المنسدلة الخاصة بالمدن والتي أسميناها list2
القائمة المنسدلة للمدن تأخذ احتمالين ، الاحتمال الأول وهو عند استعراض الصفحة لأول مره تظهر مدن الدولة المحدد افتراضيا ً في القائمة المنسدلة الأولى ، والاحتمال الثاني هو عندما يقوم المستخدم بتغيير الدولة تتغير معها الدولة .
سنأخذ أولا ً الاحتمال الأول وهو عند استعراض الصفحة لأول مره .
بما أن القائمة المنسدلة للمدن مرنه وغير ثابتة أي تتغير حسب الخيار الموجود في القائمة المنسدلة الأولى وكذلك حسب اختيار المستخدم إذن في هذه الحالة سأستخدم لغة من نوع Client-side حتى تفي بالغرض , سأستخدم لغة الجافاسكربت Javascript واختصارا ً للوقت والجهد سأستخدم مكتبة jQuery كونها ستسهل علينا الأمر خصوصا ً عند التعامل مع تقنية الاجاكس Ajax.
بعد تضمين مكتبة jQuery الى مشروعنا سأبدأ بتعريف دالة بلغة الجافاسكربت باسم getCities هذه الدالة هي المسئولة عن تغيير محتويات القائمة المنسدلة للمدن list2 ، تقوم بإرسال قيمة الدولة الى ملف Cities.php ثم يتم الاستعلام عن مدن الدولة في ملف Cities.php بعد المعالجة تقوم دالة getCities بأخذ القيم المرجعة بعد الاستعلام من ملف Cities.php ووضعها في القائمة المنسدلة للمدن list2 ، كود الدالة سيكون كا التالي :
function getCities()
{
// جلب قيمة الخيار المفعل حاليا ً في القائمة المنسدلة للدول
var countryValue = $("#Countries").val();
// مسار مجلد الملفات المؤقته
var temCity = "tempCities/";
// مسار الملف المؤقت للدولة المحددة في القائمة المنسدلة للدول
var tempURL = temCity + countryValue + ".txt";
// يتم استخدام هذا المتغير في حالة لم يكن هناك ملف مؤقت للدولة
// يتم ارسال البيانات الى ملف البي اتش بي عن طريق المصفوفة بوست
var dataPost = "co_val=" + countryValue;
// اظهار رسالة التحميل للمستخدم مابين اختيار الدولة وعرض المدن
$("#loading").fadeIn(100);
// استخدام تقنية الاجاكس عن طريق مكتبة الجيكوري لجلب مدن الدولة
$.ajax(
{
url : tempURL,
// اذا لم يتم العثور على الملف المؤقت لمدن الدولة
error : function()
{
$.ajax({
url : "Cities.php",
type : "POST",
data : dataPost,
success : function(result)
{
$("#loading").fadeOut(100);
// اخفاء القائمة المنسدلة للمدن في حالة لم يتم ادخال اي مدن للدولة
(result == "null") ? $("#Cities").hide(0) : $("#Cities").show(0);
// اضافة المدن للقائمة المنسدلة للمدن
$("#Cities").html(result);
}
})
},
// جلب البيانات من الملف المؤقت للدولة
success : function(result)
{
$("#loading").fadeOut(100);
(result == "null") ? $("#Cities").hide(0) : $("#Cities").show(0);
$("#Cities").html(result);
}
})
}كل سطر برمجي به تعليق للتوضيح , لا مشكلة إذا لم تفهم الكود بشكل كامل سيتضح إن شاء الله في الأسطر القادمة .
سأوضح الفكرة العامة للكود بشكل مختصر , مثل ما ذكرت في الاعلى الكود في الأعلى عبارة عن دالة هذه الدالة مهمتها الأساسية هي جلب البيانات من قاعدة البيانات آو من الملف المؤقت , ترسل قيمة الحقل المحدد في القائمة الأولى عن طريقة تقنية الاجاكس باستخدام POST هذا في حالة لم يكن هناك ملف مؤقت , في حالة هناك ملف مؤقت لمدن الدولة يتم جلب البيانات من الملف المؤقت .
بعد أن عرفنا الدالة سنقوم الآن باستخدامها ، مثل ما ذكرت في الأعلى آن هناك احتمالين للقائمة المنسدلة الأولى , الاحتمال الأول وضحته بالأعلى وهو عند استعراض الصفحة لأول مره والاحتمال الثاني هو عندما يقوم المستخدم بتغيير الدولة في القائمة الأولى , واختصارا ً للجهد قمت بتعريف الدالة التي بالأعلى وهي التي سنستخدمها في الاحتمالين أي عند البداية وعند تغيير خيارات الدول , وكود استخدام الدالة سيكون بالشكل التالي :
$(document).ready(function()
{
getCities();
$("#Countries").change(function()
{
getCities();
})
})قد تلاحظ آن الاكواد غريبة بعض الشيء إذا لم تكن لديك خلفية مسبقة عن مكتبة jQuery أو الجافا سكربت , لذلك أي شي غير واضح لا تنسى أن تسأل عنه حتى أوضحه لك أن شاء الله
إلى هنا نكون قد انتهينا من ملف form.php والكود النهائي لهذا الملف يفترض أن يكون بالشكل التالي :
<html>
<head>
<title>Change List</title>
<script type="text/javascript" src="jQuery.js"></script>
<script type="text/javascript">
function getCities()
{
// جلب قيمة الخيار المفعل حاليا ً في القائمة المنسدلة للدول
var countryValue = $("#Countries").val();
// مسار مجلد الملفات المؤقته
var temCity = "tempCities/";
// مسار الملف المؤقت للدولة المفعلة في القائمة المنسدلة للدول
var tempURL = temCity + countryValue + ".txt";
// يتم استخدام هذا المتغير في حالة لم يكن هناك ملف مؤقت للدولة
// يتم ارسال البيانات الى ملف البي اتش بي عن طريق المصفوفة بوست
var dataPost = "co_val=" + countryValue;
$("#loading").fadeIn(100);
// استخدام تقنية الاجاكس عن طريق مكتبة الجيكوري لجلب مدن الدولة
$.ajax(
{
url : tempURL,
// اذا لم يتم العثور على الملف المؤقت لمدن الدولة
error : function()
{
$.ajax({
url : "Cities.php",
type : "POST",
data : dataPost,
success : function(result)
{
$("#loading").fadeOut(100);
// اخفاء القائمة المنسدلة للمدن في حالة لم يتم ادخال اي مدن للدولة
(result == "null") ? $("#Cities").hide(0) : $("#Cities").show(0);
// اضافة المدن للقائمة المنسدلة للمدن
$("#Cities").html(result);
}
})
},
// جلب البيانات من الملف المؤقت للدولة
success : function(result)
{
$("#loading").fadeOut(100);
(result == "null") ? $("#Cities").hide(0) : $("#Cities").show(0);
$("#Cities").html(result);
}
})
}
/*
-----------------------
*/
$(document).ready(function()
{
getCities();
$("#Countries").change(function()
{
getCities();
})
})
</script>
</head>
<body>
<form method="POST" action="gg.php">
<select name="list1" id="Countries">
<?php
$query = mysql_query("SELECT id,name,value FROM countries");
while($rows = mysql_fetch_array($query))
{
echo '<option value="'.$rows['value'].'">'.$rows['name'].'</option>';
}
?>
</select>
<select name="list2" id="Cities">
</select>
<input type="submit" value="go" />
<form>
<div id="loading" style="display:none">Loading</div>
</body>
</html>نتقل الآن إلى ملف Cities.php هذا الملف دورة الأساسي في جلب المدن من قاعدة البيانات , طبعا ً لا نتعامل معه بشكل مباشر إنما عن طريق الاجاكس من ملف form.php
كود ملف Cities.php سيكون بالشكل التالي :
$couVal = $_POST['co_val'];
if($couVal)
{
$queryTown = mysql_query("SELECT name,value FROM cities WHERE country_value = '$couVal'");
$num = mysql_num_rows($queryTown);
if($num > 0)
{
while($rows = mysql_fetch_array($queryTown))
{
echo '<option value="'.$rows['value'].'">'.$rows['name'].'</option>';
$fp = fopen("tempCities/".$couVal.".txt","a");
fwrite($fp,'<option value="'.$rows['value'].'">'.$rows['name'].'</option>');
}
fclose($fp);
}else
{
echo 'null';
}
}شرح الكود :
أولا ً قمت بتعريف متغير محتواه عبارة عن المصفوفة POST
لو رجعنا إلى الخلف قليلا ً سنلاحظ أننا استخدامنا تقنية الاجاكس وكذلك استخدمنا POST لإرسال البيانات إلى ملف Cities.php ، مرننا البيانات عبر قيمة co_val
البيانات التي أرسلناها هي عبارة عن قيمة الخيار المحدد حاليا ً في القائمة المنسدلة للدول , نرسل هذه القيمة إلى ملف Cities.php ثم نستعلم عن المدن المتعلقة بهذه الدولة , إذن المتغير couVal يحتوي على قيمة Value للمدينة المحدد في القائمة المنسدلة للدول .
في السطر التالي قمت بوضع شرط لاختبار أن هناك فعلا ً قيم مرسلة ، هذه القيمة هي عبارة عن رمز الدولة ليتم الاستعلام عنه
ثم في الأسطر التالية قمت بعملية استعلام عادية وطباعة القيم , الأمر المهم الأخر في هذا الكود هو أنني قمت بتنفيذ دالة fopen لعمل ملف مؤقت في مجلد tempCities هذا الملف حتى لا يتم الاستعلام مره أخرى من قاعدة البيانات ويتم اخذ البيانات من الملف المؤقت للتخفيف على الخادم وكذلك للسرعة .
إلى هنا انتهى الدرس , اعذروني إذا كانت هناك أي أخطاء أو لم أقم بإيصال المعلومة بشكل صحيح ، أسعد باستقبال أسئلتكم واستفساراتكم .
دمتم بود M.B.O