حلول برمجية (1) :
كثيرا ما تعترض المبرمج مشكلات في برنامجه، فيبحث عن حلول لها، والبرمجة فكر مفتوح يختلف المبرمجون في إيجاد الحل، وإن اتفقوا في النتيجة.
من المشكلات التي واجهتني، ووجهت غيري هي مشكلة النصوص المضبوطة بالشكل.
فبعد أن انتهيت من برمجة برنامجي الشعر والنثر ، وانتقلت إلى مرحلة التجربة تبين لي أن محرك البحث لا يبحث في النصوص المضبوطة بالشكل.
فمثلا القصيدة مضبوطة بالشكل، والزائر يبحث عن كلمة، ومن المعتاد أنه لن يضبط الكلمة بالشكل. فلهذا لا تظهر له نتيجة.
أول أمر فكرت فيه هو البحث عن أوامر SQL تتجاهل بعض الحروف، بحيث توضع قائمة بالحروف، تُتَجاهل من قبل مزود القاعدة.
لكنني لم أفلح من في العثور على هذا الأمر في Mysql
وقد يرجع هذا إلى أن هذه المشكلة ليست في اللغة الإنجليزية، فهم لن يتطرقوا إليها، ولو كان مبرمجو قاعدة Mysql عربًا لوضعوا هذا في حسبانهم.
المرحلة الثانية :
بما أن أمر التجاهل ليس متوفرًا، فعليَّ أن أبحث عن حل، فتوصلت إلى زيادة حقل في جدول النص يتضمن النص مضبوطا بالشكل.
فالجدول مثلا يتكون من :
Id,author,text
فزدت عليه
text_ta
بحيث يكون text_a لعرض النص أمام الزائر، و text للبحث من قبل قاعدة البيانات.
ولست أول من توصل إلى هذا الحل، فقد توصل إليه آخرون؛ لكن اختلف الطريقة، فالأخ قهوة نت عمل جدولين كاملين لبرنامج القرآن الكريم أحدهما فيه النص مضبوطا، والآخر دون ضبط.
وكان يمكنه الاختصار بحيث يضع جدولا وحدا، وحقلين للنص.
هذه الطريقة حلَّت المشكلة؛ لكن فيها عيبا، وهو أن قاعدة البيانات ستتضخم لوجود نصين بالحجم نفسه.
لكنه أهون من ألا يجد الزائر بغيته وهي متوفرة!
هل انعدمت الحلول؟
لا
فكرت في حل آخر.
من المعلوم أن البحث في القاعدة لا يكون عن طريق مترجم php بل عن طريق مزود القاعدة. وهذا يعني أن عملية البحث ليست من اختصاصك، بل من اختصاص القاعدة.
وعلى هذا فالبحث في القاعدة أفضل، وأهون من البحث في الملفات النصية.
نتيجة لما سبق :
فكرت في إنشاء ملف نصي للنصوص المضبوطة بالشكل، والجدول تكون فيه النصوص غير مضبوطة بالشكل.
فالنصوص التي في القاعدة للبحث، والنصوص التي في الملفات للعرض.
وتكون الملفات النصية في مجلد اسمه text_ta
يكون الرقم التسلسلي (id) هو اسم الملف
1.text
2.text
3.text
وعند عرض النص، يطلب الملف
Include "$id.text";
حيث $id هو الرقم التسلسلي.
هذا حل جيد.
لكن فيه عيبا
وهو أنه يمكن استعراض هذه الملفات النصية.
لكن هناك حل
وهو جعل هذه الملفات بامتداد .php
يكون هناك متغير اسمه
$data
يحتوي على النص المضبوط
ويطلب الملف
Include "$id.php";
ثم يطبع النص
Echo $data;
يلزمك في هذه الطريقة إنشاء ملف مستقل في لوحة التحكم من أجل التعامل مع هذه الملفات إضافة، وتحريرًا، وحذفًا.
هل انتهت الحلول؟
لا
هناك حل آخر توصلت إليه لا يعتمد على الملفات النصية بل يعتمد على القاعدة نفسها، وبجدول واحد فقط!
ولكي يسهل الفهم، فإني سأطبق على برنامج القرآن الكريم من برمجة الأخ فهوة نت.
تتكون القاعدة من جدولين :
quran
وفيه النصوص مضبوطة بالشكل
و
quran1
وفيه النصوص مجردة من الشكل.
وإليك طريقة البحث :
function dosearch ($searchterm) {
هنا دالة البحث (dosearch) تتضمن متغيرًا؛ وهو ($searchterm) وهي الكلمة المراد بحثها
top_part ();
إحالة على هذه الدالة لطباعة رأس الصفحة.
$xyz = mysql_query ("select q1.chapter,q1.soraano,q1.pageno,q1.soraaname,q.ayaa,q1.ayaano from quran1 as q1 left join quran as q on q1.id=q.id where q1.ayaa like '%$searchterm%'");
طلب البحث من قاعدة البيانات عن الكلمة المدخلة، حيث يبحث في الحقل quran1 لأن النص فيه غير مضبوط بالشكل، ثم يدمجها الحقول بـ quran حيث النص فيه مضبوط في الشكل.
if (mysql_num_rows($xyz) != 0) {
الاستعلام عن عدد النتائج، فإن كانت هناك نتيجة :
echo "عدد نتائج البحث: " . mysql_num_rows($xyz);
echo "<table width=\"80%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">"
."<tr><td><ul>";
طباعة عدد النتائج، ثم رأس الجدول
while(list($chapter,$soraano,$pageno,$soraaname,$ayaa,$ayaano)=mysql_fetch_row($xyz)) {
حلقة تكرار لعرض النصوص
ثم :
$partofayaa = substr($ayaa, 0, 30);
اقتطاع جزء من الآية ( لا أعلم لماذا أدرجه الأخ قهوة نت )
ثم :
echo "<li><a href=\"quran.php?doWhat=gosoorah&soraahno=$soraano&ayaahno=$ayaano\"><font color=green>$ayaa ... </font></a>"
." ($soraaname-$chapter) </li>";
}
طباعة النتائج، ثم إغلاق حلقة التكرار
ثم :
echo "</ul></td></tr></table>";
إغلاق الجدول
فإن لم تكن هناك نتائج
} else {
echo "لا يوجد نتائج للبحث";
}
طباعة الرسالة.
ثم :
mysql_free_result($xyz);
lower_part (0);
تحرير قاعدة البيانات، ثم طباعة الجزء السفلي
ثم
}
إغلاق الدالة.
انتهى
الفكرة التي توصلت إليها، هي سرد القاعدة كاملة!، ثم تجريد كل آية من علامات التشكيل، فإن حصل توافق بين الكلمة المدخلة وجزء من الآية فإنه يطبع النتيجة
وإليك التطبيق :
function dosearch ($searchterm) {
هنا دالة البحث (dosearch) تتضمن متغيرًا؛ وهو ($searchterm) وهي الكلمة المراد بحثها
top_part ();
إحالة على هذه الدالة لطباعة رأس الصفحة.
ثم :
$xyz = mysql_query ("
SELECT chapter,soraano,pageno,soraaname,ayaa,ayaano FROM quran");
طلب استعلام القاعدة كاملة.
ثم :
echo "<table width=\"80%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">"
."<tr><td><ul>";
طباعة رأس الجدول.
ثم
تحديد عدد النتائج بصفر :
$result=0;
ثم
حلقة تكرار لما للطلب السابق :
while(list($chapter,$soraano,$pageno,$soraaname,$ayaa,$ayaano)=mysql_fetch_row($xyz)) {
ثم
$old_ayaa =$ayaa;
تحديد قيمة $old_ayaa لتوافق $ayaa من أجل طباعة النتائج مشكلة
ثم :
تحديد خانات علامات التشكيل :
$tashkeel = array(
"/ّ/",
"/َ/",
"/ً/",
"/ُ/",
"/ٌ/",
"/ِ/",
"/ٍ/",
"/ُ/",
"/ْ/",
"/ُ/",
);
ثم :
$re = "";
$old_ayaa=preg_replace($tashkeel, $re, $old_ayaa);
وضع الاستبدال بفراغ، ثم استبدال علامات التشكيل في كل آية بفراغ، بحيث تكون مجردة من العلامات.
ثم
ننظر :
if (preg_match("/$searchterm/i","$old_ayaa")) {
إذا كانت الكلمة المدخلة توافق الآية المجردة من علامات التشكيل
$result=$result+1;
فنجعل عدد النتائج يزداد بقيمة واحدة
ثم نحدد الطباعة الأخيرة
$show_search .= "<li><a href=\"q_1.php?doWhat=gosoorah&soraahno=$soraano&ayaahno=$ayaano\"><font color=green>$ayaa ... </font></a>"
." ($soraaname-$chapter) </li>";
}
مع إغلاق شرط المطابقة.
ثم إغلاق شرط التكرار
}
ثم ننظر :
/code]
if ($result) {
echo "عدد نتائج البحث: " . $result;
} else {
echo "ليست هناك نتائج للبحث";
}
إن كانت هناك نتائج للبحث فإننا نطبع عددها، فإن لم يكن هناك نتائج فنطبع الرسالة.
ثم
echo $show_search;
نطبع النتائج المتحصلة في حلقة التكرار السابقة
ثم
echo "</ul></td></tr></table>";
نغلق الجدول
ثم :
mysql_free_result($xyz);
lower_part (0);
نحرر قاعدة البيانات، ثم نطبع الجزء السفلي
ثم
{
نغلق الدالة
هذه الطريقة تغنيك عن كتابة حقلين أو جدولين للنصوص، أو كتابة ملفات نصية
لكن فيها عيبا
اتركه لكم
هل انتهت الحلول؟
لا
قد يعثر أحدكم على حل
هل أنت في حيرة؟
لا
اختر الطريقة التي تراها مناسبة .
ختاما:
مصدر البرمجتين :
الأصلية :
function dosearch ($searchterm) {
top_part ();
$xyz = mysql_query ("select q1.chapter,q1.soraano,q1.pageno,q1.soraaname,q.ayaa,q1.ayaano from quran1 as q1 left join quran as q on q1.id=q.id where q1.ayaa like '%$searchterm%'");
if (mysql_num_rows($xyz) != 0) {
echo "عدد نتائج البحث: " . mysql_num_rows($xyz);
echo "<table width=\"80%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">"
."<tr><td><ul>";
while(list($chapter,$soraano,$pageno,$soraaname,$ayaa,$ayaano)=mysql_fetch_row($xyz)) {
$partofayaa = substr($ayaa, 0, 30);
echo "<li><a href=\"quran.php?doWhat=gosoorah&soraahno=$soraano&ayaahno=$ayaano\"><font color=green>$ayaa ... </font></a>"
." ($soraaname-$chapter) </li>";
}
echo "</ul></td></tr></table>";
} else {
echo "لا يوجد نتائج للبحث";
}
mysql_free_result($xyz);
lower_part (0);
}
طريقتي :
function dosearch ($searchterm) {
top_part ();
$xyz = mysql_query ("
SELECT chapter,soraano,pageno,soraaname,ayaa,ayaano FROM quran");
mysql_num_rows($xyz);
echo "<table width=\"80%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">"
."<tr><td><ul>";
$result=0; while(list($chapter,$soraano,$pageno,$soraaname,$ayaa,$ayaano)=mysql_fetch_row($xyz)) {
$partofayaa = substr($ayaa, 0, 30);
$old_ayaa =$ayaa;
$tashkeel = array(
"/ّ/",
"/َ/",
"/ً/",
"/ُ/",
"/ٌ/",
"/ِ/",
"/ٍ/",
"/ُ/",
"/ْ/",
"/ُ/",
);
$re = "";
$old_ayaa=preg_replace($tashkeel, $re, $old_ayaa);
if (preg_match("/$searchterm/i","$old_ayaa")) {
$result=$result+1;
$show_search .= "<li><a href=\"q_1.php?doWhat=gosoorah&soraahno=$soraano&ayaahno=$ayaano\"><font color=green>$ayaa ... </font></a>"
." ($soraaname-$chapter) </li>";
}
}
if ($result) {
echo "عدد نتائج البحث: " . $result;
} else {
echo "ليست هناك نتائج للبحث";
}
echo $show_search;
echo "</ul></td></tr></table>";
mysql_free_result($xyz);
lower_part (0);
}
إذا طبقتها، فاحذف جدول quran1 من قاعدة البيانات، وتمتع بمساحة إضافية!