قائمة البرمجة > لغة Perl

تعليم لغة بيرل Perl و سي جي آي CGI

الكاتب:


المصدر: http://www.angelfire.com/rnb/forarabs

الدرس الأول
الدرس الثاني
الدرس الثالث
الدرس الرابع


الدرس الأول

لماذا بيرل ؟

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

بناء نص بيرل :

نصوص بيرل هي ببساطة ملفات نص Text Files يمكنك عملها باستعمال محرر نصك المفضل . و لا يمكنك فعل أي شيء بهذه الملفات بدون مترجم لغة بيرل أي نسخة من اللغة نفسها و يمكنك الحصول عليه من هذه الوصلة http://www.activestate.com/Products/ActivePerl/?psbx=1 حيث يجب أن تنزل أولاً البرنامج Windows Installer +2.0 ، ثم اضغط على زر next لتصل إلى صفحة أخرى تطلب بعض المعلومات منك ، يمكنك تركها خالية ثم اضغط على الزر next مرة أخرى لتصل إلى صفحة أخرى تستطيع فيها أن تنزل المترجم بالنقر على الوصلة MSI ، ثم يجب أن تركب البرنامج الأول ، و بعد هذا تستطيع أن تركب نسخة المترجم ثم أعد تشغيل الحاسب . الآن يمكنك أن تبدأ ، افتح محرر نصك المفضل و اكتب السطور التالية :

#!/c:/perl/bin

print "Hello World!","\n";

# End hello.pl

و احفظ الملف بإسم Hello.pl ، الآن اذهب إلى نافذة الدوس Dos و اذهب إلى المكان الذي حفظت فيه الملف Hello.pl و اكتب perl Hello.pl ، يجب أن تبدو النتيجة مثل الصورة التالية :

مبروك .... أنت الآن مبرمج بيرل .

تحليل المثال :

# هذه العلامة هي رمز التعليق في بيرل و هي تعني أن أي شيء يتبعها حتى نهاية السطر يتجاهله المترجم . و هذا هو المكان الذي تستطيع فيه توثيق برنامجك حتى يستطيع الآخرين ، أو أنت بعد عدم اقترابك من البرنامج لمدة أشهر أن تفهم عم يدور هذا البرنامج . في هذا المثال لم نذكر سوى سطر تعليق واحد فقط و هو أساسي في كل برامج بيرل و هو يحدد مكان المترجم الخاص باللغة في قرصك الصلب . و بالرغم من أن هذا السطر لا تتطلبه نسخة بيرل الخاصة بالويندوز إلا أن المترجم قد يعطيك رسالة خطأ إذا تجاهلته أو كتبت المسار بطريقة غير صحيحة .

استعملنا في هذا المثال وظيفة واحدة فقط هي وظيفة اطبع print و في هذه الحالة فإننا نخبر print أن تطبع إلى الشاشة العبارة الموجودة أمامها بين علامتي الاقتباس ثم نضع فاصلة (و هي مهمة جداً) و نتبعها برمز السطر الجديد "n\" و هذه الشرطة المائلة الخلفية يطلق عليها رمز هروب لأنها تعطي الحرف الذي يأتي بعدها معنى خاص . ثم في نهاية السطر نضع فاصلة منقوطة ، و هي هامة جداً و كل سطور الشفرة في بيرل يجب أن تنتهي بها ، لأن المترجم لن يستطيع وحده معرفة أين ستنتهي جملة الشفرة التي قد تطول لأكثر من سطر .

إذا أردت أن تظهر الجملة نفسها على الشاشة بين علامتي اقتباس فيمكنك استعمال رمز الهروب و هو علامة الشرطة المائلة الخلفية \ قبل كل علامتي اقتباس تريدهما أن يظهرا في النص المطبوع على الشاشة . فمثلاً السطر التالي :

print "\"hello world\"","\n";


سوف ينتج عنها الشكل التالي :


هل فهمت الآن معنى رمز الهروب \ . السطر الأخير من البرنامج كما عرفنا يبدأ برمز التعليق # و هو يخبرنا بنهاية البرنامج .



الكميات العددية و القوائم في بيرل :

هنا سوف نتعامل مع ثلاثة مفاهيم جديدة هي المتغير - الكمية العددية - و القائمة .

المتغير : معلومات مخزنة في مكان ذاكرة محدد .

الكمية العددية : متغير واحد يحدد معلومات عددية أو معلومات عن رمز سلسلة .

القائمة : عدد من الكميات العددية المخزنة بالتعاقب في متغير واحد .

السلسة String في معظم لغات البرمجة هي سلاسل بسيطة من الحروف مثلاً "الاتحاد قوة" هي سلسلة ، و لاحظ أنها بين علامتي اقتباس . هذا مهم في بيرل

الشيء المهم تذكره عن المتغيرات العددية أنها دائماً تبدأ بعلامة الدولار $ و يمكنك تسميتها بأي شيء تريده ، المهم ألا تنسى علامة الدولار .

تحذير : بيرل لغة حساسة جداً أي أنها تميز بين الحروف الكبيرة و الصغير Capital and Small Letters . لذلك فإنها سوف تعتبر

$Variable Name

و

$variable name

متغيرين عدديين مختلفين .

لتوضيح مفهوم تخزين المعلومات في متغيرات عددية سوف نسوق المثال التالي ، افتح محرر نصك و اكتب السطور التالية و احفظها باسم hello2.pl :

#!c:/perl/bin

# Hello 2. a slightly more sophisticated "hello world"

$Hello="hello world"; # String variable

$TimeAround=2; # Numric variable

print $Hello. " for the ". $TimeAround. "nd time","\n";

# End Hello2.pl

عندما تشغل البرنامج سوف ترى مثل هذه الشاشة :


لاحظ المسافات في سطر print خاصة في كلمتي for the بين علامتي الاقتباس ، فقد وضعنا مسافة بعد علامة الاقتباس الأولى مباشرة و مسافة قبل علامة الاقتباس الثانية ، و هذا حتى لا يتشابك النص مع ما قبله أو بعده .

القوائم هي مجموعة من المعلومات أو المتغيرات مخزنة في مجموعة واحدة يمكن لأي شيء أن يدخل فيها سواء كان سلاسل أو أرقام أو حروف . و يحمل العنصر الأول فيها رقم صفر .

رمز القائمة هو @ و تستطيع أيضاً تسميتها كما تشاء المهم ألا تنسى @ ، مثلاً :

@Numbers=(1,2,3,4,5,6);

هي قائمة تحتوي على ست عناصر أو أرقام . يمكننا أن نشير إلى عنصر واحد منها أو عدد واحد فقط كمتغير عددي كالآتي :

$OneNumber= $Numbers[2];

استعملنا هنا للإشارة إلى القائمة Numbers علامة الدولار $ و هي علامة المتغير العددي بدلاً من @ و هي علامة القائمة و هذا لأن العنصر الذي أشرنا إليه في القائمة و هو العنصر الثاني هو متغير عددي . كذلك يمكنك استعمال الصيغة التالية إذا كانت القائمة تتكون من متغيرات عددية فقط :

@Numbers=(1..6);

هذه الصيغة لتعريف القائمة كلها التي تحتوي على الأرقام من 1 إلى 6 و ليس لاستدعاء عنصر واحد من عناصرها .

عندما نضع سلسلة أو سلاسل في قائمة أو مجموعة يجب أن نميزها عن غيرها من عناصر القائمة و ذلك بأن نضعها بين علامات اقتباس مفردة و ليست مزدوجة كالآتي :

@list=(1,2,'Red','Green',3);

هذا المثال لقائمة تحتوي على متغيرات عددية و سلاسل حرفية معاً .



CGI أو Common Gateway Interface و بيرل :

سي جي آي هي المفتاح الذي يجعل لغة بيرل تتلائم مع الويب . فالسي جي آي ليست لغة برمجة بل هي كما يقرر الأسم بوضوح (البوابة البينية المشتركة) فهي برنامج بيني يأخذ مدخلاته من صفحة هتمل موجودة على الويب ثم تمرره لبرنامج بيرل الذي يعالجها حسب الغرض المصنوع له ثم يعيده إلى أنبوبة السي جي آي التي تمرره بدورها إلى خادم الويب ليعرضه كصفحة ويب . و يمكنك إيجاد قدر كبير من المعلومات حول المواصفات الرسمية لسي جي آي في هذا الموقع . http://hoohoo.ncsa.uiuc.edu/cgi/interface.html


الدرس الثاني



إعداد خادم HTTP :

لا يمكنك تشغيل تطبيقات CGI بدون خادم ويب Web Server ، و الأغلبية العظمى من خوادم الويب يعملوا على نظام يونيكس Unix إلا أن هناك العديد من خوادم الويب العاملين على الويندوز أيضاً . من هذه الخوادم خادم Sambar Server و هو مجاني يمكنك الحصول عليه من هذا الموقع http://www.sambar.com. بعد تنزيله فك ضغطه و شغل الملف setup.exe و بعد ذلك يمكن تشغيله من قائمة إبدأ Start ، و هو لا يظهر نافذة عند بدء تشغيله ، فقط ستلاحظ أيقونته بجوار الساعة في صينية النظام System Tray . و إذا كان هذا البرنامج فعالاً فإنه يحيل حاسبك إلى خادم ويب مصغر تستطيع فيه تشغيل برامج البيرل و السي جي آي كأي خادم ويب عادي على الإنترنت ، و لا يلزمك حتى الاتصال بالإنترنت .

الكتابة بالهتمل :

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

الآن نحن لم نعد نطبع إلى الشاشة ، بل إلى خادم الويب و بالتالي نحتاج إلى مخاطبة خادم الويب باللغة التي يفهمها (الخاضعة لمقياس مايم) و هي لغة هتمل HTML ، و لذلك فإننا يجب أن نعيد بناء برنامجنا الأول ليرسم صفحة ويب يستطيع خادم الويب فهمها و عرضها .

افتح محرر النص و اكتب السطور التالية ثم احفظها باسم hellowww.pl في الفهرس الذي يتوقع خادم الويب أن يجد فيه برامج CGI و هو عادة يكون في c:\program files\sambar\cgi-bin :

#!c:/perl/bin

#hellowww.pl

# A perl program that draws a web page.

print "Content-type: text/html","\n\n"; # MIME header

print "<html>","\n";

print "<head>";

print "<title>Perl Meets the World Wide Web</title>","\n";

print "</head>","\n";

print "<body>","\n";

print "<h1>Hello World !</h1>","\n";

print "</body>","\n";

print "</html>","\n";

# End Hellowww.pl

الآن جئنا للنقطة المهمة ، كيف تشغل هذا البرنامج . تأكد أولاً من أن Sambar Server فعال و أن أيقونته موجودة في صينية النظام ثم افتح متصفحك و اكتب فيه العنوان التالي localhost/cgi-bin/hellowww.pl و اضغط زر الإدخال . هل كان الناتج مثل هذه الصورة :


تهانينا .. لقد قمت بكتابة و تشغيل أول برنامج سي جي آي خاص بك .

في هذا البرنامج جمل اطبع print أصبحت تكتب شفرة هتمل HTML . و قد عرف الخادم ماذا يفعل في هذا البرنامج بسبب أول سطر قابل للتنفيذ في البرنامجprint "Content-type: text/html فهو قد أخبر الخادم أن محتوى المعلومات المرسلة إليه هي نص و أن هذا النص من نوع HTML . باقي البرنامج يطبع جمل هتمل أساسية .

الوظائف الفرعية Subroutines في بيرل :

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

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

استعمال أمر Require :

برنامج hellowww.pl لا يفعل أي شيء أكثر من مرة واحدة و بالرغم من ذلك فهو يحتوي على بعض الشفرة التي ستستعملها على الأقل مرة واحدة في كل برنامج سي جي آي تكتبه . هذه الأجزاء هي التي ترسم حدود صفحة الويب و هي تتكون من جزئين : جزء علوي هو الآتي :



print "Content-type: text/html","\n\n"; # MIME header

print "<html>","\n";

print "<head>";

print "<title>Perl Meets the World Wide Web</title>","\n";

print "</head>","\n";

و جزء سفلي هو الذي يحدد نهاية صفحة الهتمل ، و هو الآتي :



print "</body>","\n";

print "</html>","\n";

سوف نستفيد من هذين الجزئين بأن نضع كل جزء منهما في ملف منفصل ثم نستعمل وظيفة require لاستدعائهما في الأماكن الملائمة في أي برنامج نريده . و لكن يجب أن نلاحظ أن وظيفة require تعرف لك الوظيفة الفرعية التي استدعيتها و لكنها لا تستعملها ، الآن نعرف كيف نستعملها . دعنا الآن نبدأ بعمل وظيفة فرعية من شفرة الجزء السفلي ، افتح محرر النص و اكتب هذه الأسطر :

#!c:/perl/bin

# set up a standard HTML footer section. At this point , it simply

# ends the Body and HTML sections.

sub HTML_Footer

{

print "\n","</body>","\n";

print "</html>","\n";

}

1;

# End HTML_Footer

احفظ الملف باسم htmlend.pl .

كلمة sub تعرف الشفرة الآتية بعدها بأنها وظيفة فرعية خاصة كل الشفرة ما بين أداتي الحصر المفتوحتين } { . أما HTML_Footer فهي اسم الوظيفة الفرعية الذي نستطيع أن نناديها به . أما رقم 1 الذي وضعناه كسطر منفصل في نهاية الشفرة فهو لكي يرشد المترجم أن عملية تنفيذ هذه الوظيفة الفرعية قد تمت بنجاح و أن قيمتها 1 و هي قيمة حقيقية ليست فارغة أو خاطئة ، و يمكنك الانتقال لتنفيذ باقي خطوات البرنامج .

تركيب ملف شفرة الجزء السفلي :

لنستعمل الوظيفة الفرعية التي أعددناها في htmlend.pl سوف نغير أشياء بسيطة في مثالنا السابق hellowww.pl . افتح ملف hellowww.pl باستخدام محرر النص المفضل عندك و أجر التغيرات التالية :



#!c:/perl/bin

#hellowww.pl

# A perl program that draws a web page- with subroutines.

require "htmlend.pl"; # Call in file.

print "Content-type: text/html","\n\n"; # MIME header

print "<html>","\n";

print "<head>";

print "<title>Perl Meets the World Wide Web</title>","\n";

print "</head>","\n";

print "<body>","\n";

print "<h1>Hello World !</h1>","\n";

&HTML_Footer;

# End hellowww.pl

هل لاحظت التغيير ؟ لقد أضفنا وظيفة require في أول البرنامج لتستدعي الملف htmlend.pl و لكننا لم نستفيد من محتوياته أو وظائفه في حينها ، بل استفدنا منها عندما وضعنا اسم الوظيفة الفرعية الموجودة في الملف بعد علامة & في المكان الذي احتجنا إليها فيه ، أي في نهاية البرنامج .

و لاحظ أن require تتطلب أن تظهر السلسلة الخاصة بها بين علامتي اقتباس مثل وظيفة print . بالطبع يجب عليك أن تضع ملف htmlend.pl في نفس المكان الذي يوجد فيه ملف hellowww.pl و إلا فإن وظيفة require سوف تفشل و تهدم باقي البرنامج .

تركيب شفرة الجزء العلوي :

أولاً يجب أن نضع شفرة الجزء العلوي في ملف منفصل كما تعلمنا لنستخدمه كوظيفة فرعية . افتح محرر النص و اكتب السطور التالية ثم احفظها باسم htmlhead.pl في نفس مكان الملفين السابقين كما اتفقنا :



#!c:/perl/bin

# set up a standard HTML header section

# with the page title passed to it.

sub HTML_Header

{

print "Content-type: text/html","\n\n"; # MIME header

print "<html>","\n\n";

print "<head>","\n\n";

print "<title>","@_","</title>","\n\n";

print "</head>","\n\n";

}

1;

# End HTML_Header.pl


هناك علامة جديدة مذكورة بعد < title > و هي _@ هل خمنت عملها ؟؟ سأخبرك بها بعد أن تعدل الملف التالي ، الآن عدل ملف hellowww.pl مرة أخرى كما يأتي :

#!c:/perl/bin

# hellowww.pl

# A perl program that draws a web page - with subroutines.

require "htmlhead.pl"; # call in files

requrie "htmlend.pl";

&HTML_Header ("perl meets the World Wide Web");

print "<body>","\n";

print "<h1>Hello World !</h1>","\n";

&HTML_Footer;

# End hellowww.pl

نلاحظ على هذه التعديلات أنها قد جعلت من البرنامج القصير برنامجاً أقصر قليلاً . هذا جيد فالقاعدة الأولى من الكسل و عدم الصبر هو تقليل الكتابة .

أما بالنسبة للعلامة التي جذبت انتباهنا في ملف htmlhead.pl عند السطر :

print "<title>","@_","</title>","\n\n";


العلامة @ هي واحدة من علامات الاختصار العديدة السهلة في بيرل و لكنها مربكة إلى حد ما ، و هي كما عرفنا تشير إلى قائمة أو مجموعة و هي هنا خاصة بسلسلة حرفية أو عدة سلاسل . و يمكننا أن نستبدل الشرطة _ فيها بأي سلسلة حرفية عندما نستدعي هذه الوظيفة الفرعية في برنامج آخر ، و هذا ما فعلناه ، حين استبدلنا الشرطة _ بالعبارة "perl meets the world wide web" في :

&HTML_Header ("perl meets the World Wide Web");

لاحظ أننا وضعنا السلسلة الحرفية بين علامتي اقتباس كالعادة و لكن وضعناهم بين قوسين لنعرف البرنامج أن هذه هي المقابل للشرطة الموجودة في الوظيفة الفرعية .

الآن شغل المتصفح الخاص بك ، و تأكد من أن Sambar Server فعّال و شغل الملف hellowww.pl كما تعلمنا من قبل :


كما لاحظت لا يوجد اختلاف بين ما يعرضه المتصفح الآن و ما عرضه في برنامج hellowww.pl الأول ، انت قمت بنفس العمل و لكن في وقت أقل و كفاءة أكبر .

استعمال ملف Hosts :

عندما تكتب عنوان أي موقع في المتصفح فإن هذا العنوان بالنسبة له لا يعني شيئاً ، يجب أن يكون العنوان مترجماً إلى عنوان IP مثل :

198.169.20.0

يجب أن يترجم العنوان الوصفي إلى عنوان IP قبل أن يمكنه التعامل معه ، و بالتالي فإن المتصفح يحصل على مقابل العنوان الوصفي الذي كتبته عن طريق Domain Name Server أو اختصاراً DNS و هو جدول من أسماء المجالات Domain Names مثل : www.single.com و عناوين آي بي المقابلة لها ، فيعطيه المتصفح العنوان الوصفي أو اسم المجال و يعطيه DNS العنوان العددي المقابل .

و إذا كان المتصفح الخاص بك ليس متصلاً بالإنترنت فإنه ليس لديه وسيلة لتحليل أسماء المجال أو ال Domain Names ، و مع ذلك فإن DNS هو المكان الثاني الذي يبحث فيه عن العناوين ، أما المكان الأول فهو ملف Hosts الموجود في مجلد الويندوز في جهازك :

كما ترى فهو ملف نص عادي يمكنك فتحه بأي محرر نصوص مثل Notepad . كل الأسطر في هذا الملف ما عدا السطر الأخير تبدأ بعلامة التعليق كما نعرف ، أما السطر الأخير الذي ليس به تعليق فهو يعرّف العنوان الذي يشير إلى الكمبيوتر المحلي أي جهازك و هو Localhost و مقابله في عناوين الآي بي هو (1 . 0 . 0 . 127) . الآن إذا كان Sambar Server عاملاً ، يمكنك توجيه المتصفح لديك إلى العنوان http://localhost ليعرض لك الصفحة الداخلية الأساسية لبرنامج الخادم Sambar العامل على حاسبك .

الدرس الثالث


هذا الدرس صعب إلى حد ما ، فتح مخك معي جيداً و ركز في القراءة .

بمجرد أن ابتكرنا برنامج بيرل ، فإن الطريقة الوحيدة التي يتفاعل بها مع وثيقة هتمل HTML هي الاتباع التام للقواعد و الآليات التي صممت لجعل الشبكة العالمية World Wide Web تعمل . من هذه الآليات سي جي آي CGI .

فهم متغيرات المحيط :

المحيط أو Environment هو مساحة من الذاكرة ترتبط فيها أسماء المتغيرات مع قيم السلسلة المقابلة لها . مثلاً ، إذا حاولت أن تشغل برنامج عن طريق أمر (تشغيل) Run من قائمة (إبدأ) Start و ليكن مثلاً برنامج Telnet فإن نظام التشغيل سوف يبحث في المحيط المحدد له ، و هو بالنسبة له مجموعة من المسارات و الفهارس التي يبحث فيها ليجد البرنامج و بمجرد أن يجده فإنه يشغله لك ، أما إذا لم يجده فإنه يعطيك رسالة خطأ .

إذا وضعت متغير في المحيط مرتبط بسلسلة معينة فإنه يمكنك استبدال أيهما بالآخر في أي وقت و من أي برنامج ينفذ إلى المحيط . باختصار ، فإن المحيط هو مساحة من الذاكرة فيها متغيرات ذات قيم معينة لا يشترط أن تكون أنت صانع هذه المتغيرات بل قد تكون هذه المتغيرات وضعها نظام التشغيل أو الخادم أو أي برنامج عامل على النظام في نفس الوقت .

يمكننا أن نوضح المحيط بمثال عملي كالتالي افتح نافذة الدوس Dos و اكتب السطر الآتي /

set FOOBAR="The most powerful thing in the world"

هذا السطر أسس متغير في المحيط هو FOOBAR ثم أعطى له سلسلة حرفية مقابلة له هي "The most powerful thing in the world" ، و هكذا فإن المتغير FOOBAR و مقابله موجودان في الذاكرة و يمكننا أن نستدعيهما بالأمر echo مع وضع اسم المتغير بين علامتي المتغير الخاصتين بالويندوز و هما %FOOBAR% ، هكذا يفهم الويندوز أننا نريد أن نستعرض أحد المتغيرات الموجودة في المحيط و يعرض لنا مقابله المتمثل في السلسلة الحرفية .


حسناً فهمنا الآن معنى المحيط ، بالنسبة لبيرل فإنه يصل إلى المحيط عن طريق وضعه في مجموعة مترابطة خاصة تسمى ENV% .

المجموعة المترابطة تشبه المجموعة العادية التي رمزها @ فيما عدا أن كل عضو أو عنصر في القائمة مرتبط بقيمة معينة و بالتالي فإن العنصر يتكون من جزئين : المتغير و قيمته ، و تكون العلامة المميزة للمجموعات المترابطة هي علامة النسبة المئوية % .

و يمكننا أن نستدعي المتغير FOOBAR الذي أسسناه في المحيط عن طريق بيرل بالطريقة التالية :

$FooBar=$ENV {'FOOBAR'};

أما إذا كنت تريد أن تضع متغير في المحيط فيمكنك ذلك بالطريقة التالية:

$ENV {'FOOBAR'}="The most powerful thing in the World";


حسناً ، لماذا إذن وضعنا علامة الدولار $ أمام ENV ؟ ألم نتفق على أن علامة المجموعات المترابطة ( و منها المحيط لأن بيرل يضعه في مجموعة مترابطة ) هي % ؟ حسناً تذكر أننا في الحالتين قد استدعينا أو أسسنا عنصراً واحداً فقط في مجموعة و بالتالي يعتبره بيرل قيمة عددية و يجب أن يكون مسبوقاً هو و اسم المجموعة بعلامة عددية و هي علامة الدولار $ .

إعداد متغيرات المحيط Environment :

يمكنك إعداد متغيرات المحيط بأي برنامج و هذه المتغيرات متاحة في المحيط لأي تطبيقات فرعية أخرى طالما أن البرنامج أو التطبيق الذي وضعهم يعمل ، و عندما ينتهي البرنامج تنتهي المتغيرات التي وضعها في المحيط .

و هكذا فإن المتغيرات التي يضعها الخادم في المحيط تكون متاحة لبرنامج بيرل عبر السي جي آي .

متغيرات محيط CGI :

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

المتغير

الوصف

AUTH_TYPE

طريقة توثيق الوصول

CONTENT_LENGTH

الحجم بالبايت لأي معلومة تصل

CONTENT_TYPE

نوع أي معلومة تصل

GATWAY_INTERFACE

نسخة CGI التي تعمل على الخادم

HTTP_ACCEPT

أنواع MIME التي قبلها العميل

HTTP_REFERER

عنوان URL للعميل

HTTP_USER_AGENT

نوع المتصفح الخاص بالعميل

PATH_INFO

معلومات المسار الإضافية لتطبيق CGI

PATH_TRANSLATED

PATH_INFO مترجمة إلى مسار ملف

QUERY_STRING

معلومات عنوان URL المشفرة المرسلة من نموذج HTML بوساطة أمر GET .

  REMOTE_ADDR

عنوان آي بي IP للعميل 

REMOTE_HOST

اسم المجال للعميل

REMOTE_IDENT

معلومات عن الهوية الخاصة بالعميل

REMOTE_USER

تعريف المستخدم الذي يرسله العميل

REQUEST_METHOD

طريقة العميل في الطلب ( مثل HTML أو POST أو GET )

SCRIPT_NAME

عنوان URL الخاص بتطبيق CGI

SERVER_NAME

اسم الخادم

SERVER_PORT

قناة اتصال TCP/IP التي تم طلب الاتصال منها (عادةً 80 ل HTTP )

SERVER_PROTOCOL

اسم البروتوكول الذي يستخدمه الخادم المستعمل في الطلب

SERVER_SOFTWARE

اسم البرنامج أو التطبيق الذي يستخدمه الخادم



اسم البرنامج أو التطبيق الذي يستخدمه الخادم

بعض مفاهيم بيرل الجديدة :

في عملية تصميم برنامج بيرل لطباعة متغيرات سي جي آي المحيطية لصفحة ويب سنتعلم تفاصيل مجموعات بير المترابطة و استخدام أداتين جديدتين :


استعمال وظيفة each لسحب أو استدعاء أعضاء من مجموعة مترابطة .

استعمال كتل شفرة while لإعداد دوران أو loops .

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

فرم المفاتيح هو باختصار ترجمة قيمة المفتاح Key إلى مفتاح عددي يشير إلى القيمة مما يجعل عملية البحث تتم بسرعة و كفاءة . و كما علمنا أن بيرل يقدم علامة جديدة للدلالة على المجموعات المترابطة هي علامة النسبة المئوية % .

كتابة برنامج العرض :

البرنامج الذي سنكتبه الآن سوف يأخذ كلاً من متغيرات المحيط التي ذكرناها في الجدول ، بالإضافة إلى وصف قصير لها ، في مجموعة مترابطة تسمى EnvVarlist% . ثم يعد صفحة هتمل HTML و يطبع الأسماء و القيم الخاصة بكل المتغيرات حتى ينتهي من المجموعة كلها .

المجموعة المترابطة EnvVarlist% سوف تكون طويلة إلى حد ما ، لذلك سوف نعدها بطريقة تجعلها أكثر قابلية للقراءة مثل السطر التالي :

%EnvVarlist=

(

'AUTH_TYPE', 'Server\'s Authentication method is: ',

لاحظ أن الأقواس على السطر التالي و أنها تترك مسافة قبلها في بداية السطر ، و هذه المسافات غير ضرورية .

ملاحظة : إذا أردت يمكنك كتابة برنامج بيرل بأكمله على سطر واحد طالما أن كل جملة برنامج مفصولة عن الأخرى بشكل مناسب عن طريق الفاصلة المنقوطة ; و الأقواس المفتوحة و المغلقة . و لكن مع ذلك ، البرنامج الجيد هو البرنامج الأكثر قابلية للقراءة . هذا مهم بالنسبة للآخرين الذين قد سضطرون لاستعمال شفرتك ، و هو أيضاً مهم لك ، حيث ستكون قادراً على تتبع ما تفعله بصورة أفضل إذا كانت الشفرة موضحة بشكل جيد . و القواعد العامة لتوضيح الشفرة تتضمن أنه يجب عليك ترك مسافات في بداية السطر قبل كتل الشفرة ، و ألا تمتد أسطر الشفرة أكثر من الهامش الأيمن لمحرر النص الخاص بك . ترك المسافات في بداية السطر قبل كتل الشفرة يجعل مكان كل تكتل من الشفرة يبرز بوضوح . أما الأسطر الطويلة فتتطلب منك أن تعرض حتى حافة الشاشة و تأخذ خطوة إضافية لتتمكن من قراءتهم .

سوف نضع عناصر السلسلة للمجموعة في علامات اقتباس مفردة هذه المرة للتناسق بين المفاتيح و المعلومات . و هذا سوف يسبب مشكلة ، حيث أن الفاصلة العليا في كلمة Server's سوف تنهي السلسلة لأن البرنامج سوف يعتبرها علامة الاقتباس الثانية التي تنهي السلسلة . للخروج من هذا المأزق هربنا ببساطة من الفاصلة العليا في كلمة Server's بوضع رمز الهروب \ قبلها (هل تذكره ؟) ، إنه يعطي معنى خاص للحرف الذي يليه .

هل أنت مستعد لكتابة البرنامج ؟ اكتب السطور التالية في محرر النص و احفظها بإسم cgienv.pl :

#!c:/perl/bin

# cgienv.pl

# A Perl program to list some of the common CGI environment variables.

require "html.pl"; # call in HTML header and ender

# Fill an associative array with the variable names

# and short descriptions.

%EnvVarlist =

(

'AUTH_TYPE', 'Server\'s authentication method is: ',

'CONTENT_LENGTH', 'Lenght of any attached information: ',

'CONTENT_TYPE', 'Type of any attached information: ',

'GATEWAY_INTERFACE', 'CGI version on server is: ',

'HTTP_ACCEPT', 'Client will accept these MIME types: ',

'HTTP_REFERER', 'Referrer\'s URL is: ',

'HTTP_USER_AGENT', 'Client\'s browser is: ',

'PATH_INFO', 'Extra PATH information is: ',

'PATH_TRANSLATED', 'PATH translation is: ',

'QUERY_STRING', 'Query string sent by client is: ',

'REMOTE_ADDR', 'Client\'s IP address is: ',

'REMOTE_HOST', 'Client\'s domain name is: ',

'REMOTE_IDENT', 'Identity data sent by client is: ',

'REMOTE_USER', 'User ID sent by client is: ',

'REQUEST_METHOD', 'Client\'s request method is: ',

'SCRIPT_NAME', 'URL of the CGI application is: ',

'SERVER_NAME', 'Server\'s computer name is: ',

'SERVER_PORT', 'Connection made at this port: ',

'SERVER_PROTOCOL', 'Server is using this protocol: ',

'SERVER_SOFTWARE', 'Server is running this software: '

);

# Start up an HTML document , then run the variables out to

# it with their descriptions.

&HTML_Header ("Common CGI environment variables");

print "<body>", "\n";

print "<H1>Some of the common CGI environment variables</H1>", "\n";

print "<H3><I>Note: Some variables have no value.";

print "These will be blank.</I></H3>", "\n";

print "<HR>", "\n"; # Draw a rule.

while (($EnvironVar, $Desc) = each (%EnvVarlist))

{

print $EnvironVar, ": ", $Desc, $ENV{$EnvironVar}, "<BR>", "\n";

}

# Ship the HTML ender. We're done.

&HTML_Footer;

# End cgienv.pl


هل لاحظت أننا استدعينا بوظيفة require ملف جديد اسمه html.pl ؟ لا تقلق ، هذا الملف هو مجرد تدعيم أو تجميع للملفين اللذين صنعناهما و أسميناهما بإسم htmlend.pl و htmlhead.pl ، و يمكنك صنع هذا الملف بكتابة السطور التالية في ملف و حفظه بإسم html.pl :

# html.pl

# Contains header and ender subroutines for setting

# up HTML document from Perl.



# Set up a standard HTML header section with the page title passed

# on the command line.

sub HTML_Header

{

print "content-type: text/html"; #put up standard HTTP opening line.

print "<html>", "\n\n"; # Specify HTML document .

print "<head>", "\n\n"; # Specify header section.

print "<title>", "@_", "<title>", "\n\n"; # put up the title line.

print "<head>", "\n\n"; # End header section.

} # End HTML_Header.pl.

# Set up a standard HTML footer section. At this point,

# it simply ends the body and html sections.

sub HTML_Footer

{

print "\n", "</body>", "\n\n";

print "</html>", "\n\n";

} # End HTML_Footer.

1;


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

الآن إلى البرنامج الأول cgienv.pl لقد أنشأنا مجموعة مترابطة تسمى EnvVarlist و وضعنا فيها رموز بعض متغيرات سي جي أي المحيطية الشائعة كعناصر لها و فصلنا بين كل عنصر و الآخر بفاصلة ، و تركنا مسافة قبل وضع علامة الاقتباس الأخيرة من كل عنصر و ذلك حتى لا يتشابك مع الكلمات التي سوف تأتي بعده عندما نطبعه في صفحة HTML .

تذكر أن العنصر الواحد يتكون من جزئين : المتغير و قيمته . و العنصر الأخير في المجموعة لم نضع بعده فاصلة ، و ذلك لأنه آخر عنصر في المجموعة و لا يوجد عنصر بعده .

وظيفة each و كتلة شفرة while :

while تنفذ الجملة التي بين الأقواس حتى تصبح غير صحيحة فتتوقف . هذه الجملة بين الأقواس تنقسم إلى قسمين يفصل بينهما علامة = و each :

while (($EnvironVar, $Desc) = each (%EnvVarlist))

و العبارة كلها تعني أن يضع قيمة المفتاح الأول أو العنصر الأول من المجموعة المترابطة EnvVarlist% في المجموعتين EnvironVar$ و Desc$ حيث أن العنصر الواحد في المجموعة المترابطة يتكون من جزئين كما عرفنا . ثم يزيد أو يضيف واحد لينتج بذلك قيمة المفتاح أو العنصر الثاني و يضعه في المجموعتان المذكورتان و هكذا إلى أن يصل إلى نهاية المجموعة و لا يجد عناصر أخرى فإن each تنتج قيمة NULL التي تعني الصفر إلى كل من المجموعتان EnvironVar$ و Desc$ مما يجعل جملة while غير صحيحة و ينتهي الدوران .

الدوران Loop الذي تنشؤه while لا يقتصر على الجملة التي تليها فقط ، بل تنشيء دوران آخر لطباعة عناصر المجموعتين EnvironVar$ و Desc$ في :

{

print $EnvironVar, ": ", $Desc, $ENV{$EnvironVar}, "<BR>", "\n";

}

حيث يطبع البرنامج عنصري المجموعتين مفصولين بعلامة : ، ثم يطبع بعدهما قيمة المتغير الموجود كعنصر في المجموعة EnvironVar$ الموجودة في المحيط و رمزه ENV% ، و لكننا بما أننا سنطبع قيمة مجموعة واحدة التي بدورها تمثل متغير واحد في المحيط الذي يضعه بيرل في مجموعة مترابطة تسمى ENV% فإننا سنستبدل علامة مجموعة المحيط المترابطة % بعلامة الكمية العددية $ لأننا سنأخذ عنصر واحد من عناصرها .

لاحظ بعناية عدد الأقواس في جملة while فالأقواس المفتوحة يجب أن تلائم الأقواس المغلقة ، و يجب أن تتأكد من هذا و إلا فإن المترجم سيشتكي بمرارة .

إدارة المثال :

الآن شغل المتصفح و تأكد من أن Sambar Server فعال و شغل الملف cgienv.pl كالمعتاد :


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

في هذا البرنامج بالرغم من أننا قد أدخلنا أعضاء المجموعة EnvVarlist% بالترتيب الأبجدي ، إلا أنهم لم يظهروا بهذا الترتيب عند تشغيل البرنامج ، و هذا نتيجة لعملية فرم المفاتيح التي تحدثنا عنها في وقت سابق . أيضاً لأن each و while لا يرتبان العناصر بل يأخذان المجموعة من أعلى لأسفل في الوقت الذي تكون فيه عناصر المجموعة قد تغير ترتيبها نتيجة لعملية فرم المفاتيح .

هناك وظيفة أخرى تؤدي نفس عمل each و while و لكنها ترتب العناصر في نفس الوقت و تصنفهم ، هذه الوظيفة هي sort ، و هي تعمل مع أداتين أخرتين هما :


جملة foreach التي تنشيء الدوران loop لاستخلاص عضو واحد في كل مرة من قائمة بيرل .

وظيفة keys التي تضع المفاتيح الخاصة بمجموعة مترابطة في مجموعة عادية .

غير كتلة شفرة while في cgienv.pl إلى هذا :

foreach $EnvironVar (sort (keys (%EnvVarlist)))

{

print $EnvironVar, ": ", $ENV{$EnvironVar}, "<BR>", "\n";

}


جملة foreach مثل جملة while تصنع دوران loop لتستخلص في كل مرة عنصراً واحداً فقط من المجموعة الموجودة بين الأقواس ، فيما عدا أنها لا تأخذ عنصر المجموعة المترابطة EnvVarlist مباشرة بل تأخذ قيمة المفتاح التي وضعتها وظيفة key في مجموعة عادية ، و في نفس الوقت فإنها لا تأخذها من أعلى لأسفل مثل each و while بل تأخذها حسب الترتيب الأبجدي نظراً لأنها تستعمل وظيفة sort .

لاحظ أننا استبعدنا جزء Desc$ من المثال لأنها قد تمثل مشكلة تتراوح بين عادية و متوسطة ، و نحن نريد أن نحافظ على الأشياء بسيطة لك .

و إذا شغلت الملف cgienv.pl بعد التعديل سوف ترى شكل مشابه لهذا :


حسناً ، العناصر الآن مرتبة حسب الترتيب الأبجدي .



الدرس الرابع

استعمال بيرل و سي جي آي عملياً :

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

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

من الأكثر منطقية أن تنظر للمشكلة من مفهوم أكثر عموماً و تفكر فيها ، مرحلة التفكير هذه تنقسم إلى ثلاث مراحل :


تحليل

تصميم

تطبيق

لذلك اختر كرسي مريح بعيداً عن الكمبيوتر في مكان هاديء و خذ معك ورقة أو اثنتين و قلم رصاص ، و ابدأ الرسم التمهيدي .

التحليل :

ما الذي تحتاج أن تفعله لكي تعد زوار صفحة ويب ؟ حسناً أنت تحتاج إلى :

1- تخزين رقم في مكان ما .

2- قدرة على قراءة الرقم .

3- القدرة على زيادة الرقم (إضافة 1)

4- كتابة الرقم الجديد على صفحة ويب .

5- تخزين الرقم مرة أخرى .

التصميم :

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

1.

إذا كانت تلك هي المرة الأولى التي يعمل فيها البرنامج ، فابتكر ملف ، و خزن القيمة 1 فيه ، ثم اذهب إلى الخطوة 3 .
2.

إذا كان الملف موجوداً بالفعل فافتحه و اقرأه و أضف 1 إلى القيمة التي قرأتها .
3.

اعرض القيمة الجديدة على صفحة الويب .
4.

اكتب القيمة الجديدة للملف .
5.

اغلق الملف .

التطبيق :

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

كيف يتعامل بيرل مع الملفات :

كما هو معروف فإننا لنقرأ الملف نحتاج إلى فتحه ثم بعد أن ننتهي منه يجب علينا إغلاقه . و وظائف بيرل التي تسمح بالتعامل مع الملفات هي :


open

close

read

write

print

من الأفضل دائماً أن تتعلمهم عن طريق فعلهم ، ادخل الشفرة التالية في محرر نصك :


#!c:/perl/bin

# access.pl

# First version. Creates or opens a file with a number

# in it, increments the number, writes it back.

$CountFile = "counter.dat"; # Name of counter File.

# Open the file and read it. If it doesn't exist, its "contents"

# will be read into a program variable as "0".

open (COUNT, $CountFile);

$Counter = <COUNT>; # Read the contents.

# Close the file, then reopen it for output.

close (COUNT);

open (COUNT, ">$CountFile");

# Increment $Counter, then write it back out. Put up a message

# with the new value. close the file and exit.

$Counter += 1;

print COUNT $Counter;

print "$CountFile has been written to $Counter times.\n";

close (COUNT);

# End access.pl


احفظ هذه العينة من الشفرة بإسم access.pl و شغلها مرات قليلة من نافذة الدوس (هل ما زلت تذكر كيف؟) ، اكتب الأمر perl ثم اترك مسافة ثم اكتب اسم البرنامج المراد تشغيله و تذكر أنك يجب أن تكون في نفس المجلد الذي يوجد فيه البرنامج ، و توضح الصورة التالية ما يجب أن تراه :



في كل مرة تشغل فيها البرنامج يزيد الرقم واحد . هذا هو ما يسمى بالعداد .

السطر الأول القابل للتنفيذ في البرنامج يؤسس متغير CountFile$ ، هذا المتغير هو اسم الملف الذي يجب أن يحكم إسمه قواعد تسمية الملفات في نظام التشغيل الذي تعمل عليه ، و بالطبع يمكنك تسميته كما تشاء في إطار هذه القواعد ، في هذا المثال أسميناه counter.dat .

توجيهات الملف File Handles :

سطري الشفرة التاليين ، يفتحا الملف و يقرءا أي شيء فيه :

open (COUNT, $CountFile);

$Counter = <COUNT>


الصيغة العامة لوظيفة open هي :

open (HANDLE, Expression);

حيث Expression تكون عادة اسم ملف أو متغير يحتوي على اسم ملف . أما HANDLE فتحتاج إلى شرح بسيط .

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

يمكن تشبيه handle في موقف كالتالي : أنت في غرفة مظلمة مليئة بالخزانات (جمع خزانة و ليس خزّان) أنت تعرف أن الملف الذي تريده في في الخزانة رقم 13 لكن أين هي الخزنة رقم 13 في هذا الظلام ؟ بيرل يعتبر أن الغرفة المظلمة هي الذاكرة و يريد أن يصل إلى ملف معين و لكنه لا يعرف مكانه بالتحديد ، هو يعرف فقط أنه في هذه الغرفة بالذات ، نحن نضيء له باب الخزانة التي يوجد بها الملف عن طريق توجيه handle فيعرف أن هذا هو مكان الملف فيفتح الخزانة و يأخذ المتغير الموضوع فيها و هو متغير الملف الذي أسسناه في أول البرنامج . توجيه handle في هذا المثال هو COUNT

هل رأيت المعنى الكبير الذي تعبر عنه هذه الجملة الصغيرة .

في السطر التالي :

$Counter = <COUNT>;

يمكن القراءة مباشرة من توجيه الملف بوضع العلامتين <> حوله . و هذا السطر يقرأ محتويات التوجيه COUNT الذي يدل على الملف Counter.dat و في نفس الوقت يضع هذه المحتويات في متغير جديد هو Counter$ .

السطران التاليان هما مصدر ارتباك للمبتدئين :

close (COUNT);

open (COUNT, ">$CountFile");

فلماذا نغلق الملف ثم نعيد فتحه فوراً ، و لماذا نضع المتغير CountFile$ بين علامتي اقتباس مع رمز أكبر من < أمامها ؟

حسناً ، عندما تضع علامة اكبر من < (باللغة الإنجليزية) أمام وسيط اسم الملف لفتحه فإن الملف يتم فتحه للمخرج أو للكتابة ، و سوف تبتكر الملف إذا لم يكن موجوداً ، أو تكتب فوق أي شيء موجود في الملف . أما إذا وضعت علامة أًصغر من > فهي تفتح الملف للقراءة ، و إذا لم تكتب أي علامات فإن بيرل سيعتبر علامة أصغر من > هي الأساس . أما بالنسبة لوضع علامات اقتباس حول متغير اسم الملف فإننا نضعها لتجنب ارتباك مترجم بيرل بين رمز إعادة توجيه المخرج و $ ليشير إلى متغير عددي .

الجزء الأخير من الشفرة من access.pl تنتج زوج من المفاهيم الجديدة و المثيرة :

$Counter += 1;

print COUNT $Counter;

print "$CountFile has been written to $Counter times.\n";

close (COUNT);


في السطر الأول =+ هو اختصار تمت استعارته من لغة البرمجة C ، في هذا المثال السطر الأول مطابق تماماً لكتابة :

$Counter = $Counter+1;

إذن لماذا لا نكتبه هكذا ؟ هذا لأن السطر الأول أقصر و بالتالي هو يتبع مفاهيم الكسل و عدم الصبر ، و في النهاية هي مسألة ذوق يمكنك وضع أي منهما .

يمكنك أيضاً أن تستعمل =- للطرح ، و =* للضرب ، و =/ للقسمة ، و الرقم على الجانب الأيمن لا يشترط أن يكون 1 بل يمكن أن يكون أي عدد صحيح أو متغير عددي .

أما السطر التالي :

print COUNT $Counter;

هذا السطر يخبر البرنامج أن يكتب الرقم الجديد الناتج عن عملية الإضافة في السطر السابق ، أقول يكتب الرقم الجديد في الملف المشار إليه بالتوجيه COUNT ، (اطبع هنا مستخدمة بمعنى اكتب) . أي أن معنى السطر : اطبع في الملف العدد الجديد للزوار بعد أن أضفنا إليه الرقم واحد ، و لذلك لم نضع فاصلة سفلية بعد COUNT لأننا لو وضعناها سيعامل البرنامج التوجيه COUNT كمتغير عددي أو متغير قائمة ، و بما أن COUNT يمثل المخرج لعملية الكتابة أي أن الكتابة سوف تتم في COUNT فإن البرنامج سيكتب إلى المخرج الأساسي أو الشاشة مما يؤدي إلى نتائج غريبة و طلاسم و لن يتم كتابة أي شيء في الملف المشار إليه بتوجيه COUNT . نحن لن نستخدم وظيفة write في أي مثال في هذه الدروس ، لأن print مستخدمة بشيوع أكبر ، و في الغالب هي أكثر صحة من write .

السطور الباقية في البرنامج تكتب رسالة إلى الشاشة تقول أن الملف المشار إليه بالمتغير الذي أسسناه في أول البرنامج CountFile$ قد تم الكتابة إليه عدد ( ) مرة ، طبعاً بدون الأقواس و لكني وضعتها هنا لأوضح أن البرنامج يكتب مكانها محتويات الملف المشار إليها بالمتغير Counter$ . ثم بعد ذلك يغلق الملف و ينتهي البرنامج .

إحضار عدادك إلى الويب :

هذا البرنامج الذي كتبناه سوف يعمل فقط من خلال نافذة الدوس ، و لكي نحوله إلى تطبيق مناسب للويب يجب أن نحوله إلى تطبيق CGI و ملخص الأمر هو :


جزء علوي ملائم ل HTTP من هتمل HTML يرسَل إلى الخادم .

طباعة المعلومات التي نريدها في صيغة هتمل .

جزء سفلي ملائم من هتمل يرسَل إلى الخادم .

تشغيل البرنامج من المتصفح .

باتباع هذه القواعد يمكننا أن نعدل البرنامج إلى هذه الكيفية :



#!c:/perl/bin

# access.pl

# Second version. Creates or opens a file with a number

# in it, increments the number, writes it back, then displays

# the result in a message on a Web Page.

require "html.pl"; # Get HTML header, ender.

$CountFile = "counter.dat"; # Name of counter File.

$PageTitle = "Web Page Access Counter"; # Web Page title.

# Open the file and read it. If it doesn't exist, its "contents"

# will be read into a program variable as "0".

open (COUNT, $CountFile);

$Counter = <COUNT>; # Read the contents.

# Close the file, then reopen it for output.

close (COUNT);

open (COUNT, ">$CountFile");

# Increment $Counter, then write it back out. Put up a message

# with the new value. close the file.

$Counter += 1;

print COUNT $Counter;

close (COUNT);

# Put the result up in a standard HTML document.

&HTML_Header ($PageTitle); # HTTP header info.

print "<body>\n";

print "<H1>$PageTitle</H1>\n"; # Big heading.

print "<HR>\n"; # Draw A Rule.

print "<H3>You are visitor #$Counter";

print " to our Web Page !</H3>\n";

&HTML_Footer;

# End access.pl

احفظ هذا الملف بإسم access.pl أيضاً و لكن في فهرس cgi-bin الموجود في مجلد Sambar لكي تستطيع تشغيله من المتصفح . و إذا كنت قد حفظت النسخة القديمة في نفس المكان فاحفظ فوقها الملف الجديد بنفس الاسم . إذا كان كل شيء سليماً فسوف ترى مثل هذه الصورة بعد تشغيل الملف عدة مرات من المتصفح :


أظن البرنامج واضح و لا يحتاج إلى شرح ، فقط لاحظ أننا لم نعد نضع علامة السطر الجديد n\ بين علامتي اقتباس وحدها ، بل أدخلناها مع السلسلة في نفس العلامات ، و هذا أصح و أقصر .

إدخال تحسينات على البرنامج :

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

كيف نحصل على عنوان الآي بي ؟ تذكر من الدرس السابق أن الخادم يملأ المحيط الخاص به بمقدار بمقدار كبير من المعلومات حول الكمبيوتر الذي اتصل به . و من هذه المعلومات المتغير المحيطي الذي يحتوي على عنوان آي بي للزائر و يسمى REMOTE_ADDR و يمكنك الوصول إليه باستعمال مجموعة المحيط المترابطة ENV كالتالي :

$VisitorAddress=$ENV {'REMOTE_ADDR'};

أما كيف تحصل على عنوان آي بي الخاص بك فهذا شيء لا أتعقد أنه ممكن إذا كنت تصل إلى الإنترنت عن طريق مقدم خدمة Service Provider فعنوان الآي بي الخاص بك يتغير في كل مرة تتصل فيها بالإنترنت لكن يوجد عدة برامج تستطيع أن تخبرك برقم الآي بي الخاص بك في كل مرة تتصل فيها بمقدم الخدمة . أما إذا كنت تتصل بالإنترنت مباشرة بدون مقدم خدمة فيجب أن يكون لك عنوان آي بي ثابت و المفترض أنك تعرفه بالفعل .

الآن ها هو الجزء المعدل من الشفرة :



# Second version. Creates or opens a file with a number

# in it, increments the number, writes it back, then displays

# the result in a message on a Web Page.

require "html.pl"; # Get HTML header, ender.

$CountFile = "counter.dat"; # Name of counter File.

$PageTitle = "Web Page Access Counter"; # Web Page title.

$HomeBase = "198.66.21.24"; # My IP address.

$VisitorAddress = $ENV {'REMOTE_ADDR'}; # Visitor's IP Address.

خزننا هنا رقم الآي بي الخاص بنا في المتغير HomeBase$ أما المتغير VisitorAddress$ فهو يسحب عنوان آي بي للزائر من مجموعة المحيط ENV ، و كالمعتاد يجب أن تستبدل رقم الآي بي الذي تم إعطاؤه في HomeBase$ بعنوان آي بي الخاص بك .

كيف نتمكن من المقارنة إذاً ؟ هنا سنستخدم جمل (إذا) (if) الشرطية التي تشبه جملة while حيث تبدو جملة if مثل هذه :

if (هذه العبارة صحيحة )

{

نفذ;

هذا الجزء;

من الشفرة;

}

و المعنى العام : إذا كانت العبارة بين الأقواس صحيحة ، نفذ الجزء التالي من الشفرة .

و صحة أو خطأ العبارة بين الأقواس تحدد نتيجة المقارنة التي يوجد منها نظامان : الأول خاص بالأعداد ، و الثاني خاص بالسلاسل و الجدول التالي يوضحهما :

عددي

سلسلة

معناه

==

eq

مساوي لـ

=!

ne

ليس مساوياً لـ

<

gt

أكبر من

>

lt

أصغر من

=<

ge

أكبر من أو يساوي

=>

le

أصغر من أو يساوي

<=>

cmp

لا يساوي ، نتيجة لها علامة


صحيح أن عنوان الآي بي عددي ، إلا أننا وضعناه في سلسلة و بالتالي لا يمكن أن نعامله كعدد بل سنقارنه كسلسلة أي باستخدام أدوات مقارنة السلسة الحرفية . الآن غير السطر الذي يضيف واحد إلى قيمة الملف في البرنامج access.pl و هو :

$Counter += 1;

غيره إلى التالي :

if ($VisitorAddress ne $HomeBase)

{

$Counter += 1;

}

إنه يقارن عنوان الآي بي للزائر بعنوان الآي بي المخزن عنده ، فإذا كانا لا يتساويان سوف يضيف واحد إلى العداد .

استعمال الإطارات لوضع العداد :

لتستطيع تشغيل العداد يجب أن تكون صفحة الويب بعنوان access.pl لأن البرنامج هو الذي يرسم صفحة الويب و ليس العكس . إذن لو كنت تضع العداد في الصفحة الأولى من موقعك فسيكون اسم موقعك كالتالي :

www.mysite.com/cgi-bin/access.pl

عنوان صعب أليس كذلك ، و الحل البديل هو أن تضع الصفحة الأولى في موقعك بدون عداد و هذه الصفحة تخبر الزوار أن ينقروا على وصلة link لدخول الموقع ، و بالطبع الوصلة سوف تشير إلى عنوان البرنامج www.mysite.com/cgi-bin/access.pl و هذا ليس حلاً سيئاً ، و لكنه يتطلب خطوة إضافية نوعاً ما .

أما الحل الآخر فهو تصميم الصفحة بطريقة الإطارات . و الإطارات عبارة عن تصميم الصفحة الأولى بحيث تكون مجرد هيكل يضم عدة نوافذ قد تكون اثنتان أو ثلاثة أو أي عدد تريده ، كل نافذة منهم تعرض صفحة ويب مختلفة عن الأخرى و يمكنك أن ترى مثال لصفحة الإطارات في موقعي الذي صممته بهذه الطريقة http://forarabs.8m.com . حيث تجد فيه إطارين : الأول على اليمين و فيه محتويات الموقع و العداد ، أما الثاني ففيه كلمة افتتاحية للموقع و يتم عرض المحتويات في النافذة اليسرى عند الضغط على عنوانها في النافذة اليمنى .

المهم أن الصفحة الأولى في الموقع سوف تكون منفصلة عن الصفحات الأخرى ، هي فقط تشير إلى صفحتين أخرتين ليملآ الفراغ . و يمكنك أن تجعل برنامج العداد access.pl هو إحدى النافذتين بدون أن تتكلف تغيير عنوان موقعك أو حتى رؤية الزوار لهذا الإسم الغريب بالنسبة لهم . و الصورة التالية توضح وضع برنامج العداد access.pl في صفحة إطارات :


فقط تأكد من أنك أشرت إلى برنامج العداد بمسار كامل ، أنا مثلاً أشرت إليه بالمسار :

http://localhost/cgi-bin/access.pl

أما بالنسبة للإطار الآخر فلا داعي لذكر المسار كاملاً ما دام في نفس المكان مع صفحة الإطارات الرئيسية التي أشارت إليه .