3. أساسيات PHP
3.1. مثال أول
فيما يلي برنامج يعرض الميزات الأولى لـ PHP.
3.1.1. البرنامج (exemple_01)
<?php
// هذا تعليق
// متغير مستخدم دون أن يتم إعلانه
$nom = "dupont";
// عرض على الشاشة
print "nom=$nom\n";
// مصفوفة تحتوي على عناصر من أنواع مختلفة
$tableau = array("un", "deux", 3, 4);
// عدد عناصره
$n = count($tableau);
// حلقة
for ($i = 0; $i < $n; $i++)
print "tableau[$i]=$tableau[$i]\n";
// تهيئة متغيرين بمحتوى مصفوفة
list($chaine1, $chaine2) = array("chaine1", "chaine2");
// تسلسل السلسلتين
$chaine3 = $chaine1 . $chaine2;
// عرض النتيجة
print "[$chaine1,$chaine2,$chaine3]\n";
// استخدام دالة
affiche($chaine1);
// يمكن معرفة نوع المتغير
afficheType($n);
afficheType($chaine1);
afficheType($tableau);
// يمكن أن يتغير نوع المتغير أثناء التنفيذ
$n = "a changé";
afficheType($n);
// يمكن للدالة أن تُرجع نتيجة
$res1 = f1(4);
print "res1=$res1\n";
// يمكن للدالة أن ترجع مصفوفة من القيم
list($res1, $res2, $res3) = f2();
print "(res1,res2,res3)=[$res1,$res2,$res3]\n";
// كان من الممكن استرداد هذه القيم في مصفوفة
$t = f2();
for ($i = 0; $i < count($t); $i++)
print "t[$i]=$t[$i]\n";
// اختبارات
for ($i = 0; $i < count($t); $i++)
// يعرض القنوات فقط
if (getType($t[$i]) == "string")
print "t[$i]=$t[$i]\n";
// اختبارات أخرى
for ($i = 0; $i < count($t); $i++){
// يعرض فقط الأعداد الصحيحة الأكبر من 10
if (getType($t[$i]) == "integer" and $t[$i] > 10)
print "t[$i]=$t[$i]\n";
}
// حلقة while
$t = array(8, 5, 0, -2, 3, 4);
$i = 0;
$somme = 0;
while ($i < count($t) and $t[$i] > 0) {
print "t[$i]=$t[$i]\n";
$somme+=$t[$i]; //$somme=$somme+$t[$i]
$i++; //$i=$i+1
}
print "somme=$somme\n";
// نهاية البرنامج
exit;
//----------------------------------
function affiche($chaine) {
// يعرض $chaine
print "chaine=$chaine\n";
}
//----------------------------------
function afficheType($variable) {
// يعرض نوع $variable
print "type[$variable]=" . getType($variable) . "\n";
}
//----------------------------------
function f1($param) {
// يضيف 10 إلى $param
return $param + 10;
}
//----------------------------------
function f2() {
// تُرجع 3 قيم
return array("un", 0, 100);
}
?>
النتائج:
تعليقات
- السطر 5: في PHP، لم يتم تحديد نوع المتغيرات. هذه المتغيرات لها نوع ديناميكي يمكن أن يتغير بمرور الوقت
- $nom تمثل المتغير ذي المعرف nom
- السطر 8: للكتابة على الشاشة، يمكن استخدام الأمر print أو الأمر echo
- السطر 11: تسمح الكلمة الرئيسية array بتعريف مصفوفة. المتغير $nom[$i] يمثل العنصر $i في المصفوفة $tableau.
- السطر 14: تُرجع الدالة count($tableau) عدد عناصر المصفوفة $tableau
- السطر 18: السلاسل محاطة بعلامات اقتباس " أو علامات اقتباس مائلة '. داخل علامات الاقتباس، يتم تقييم المتغيرات $variable ولكن ليس داخل علامات الاقتباس المائلة.
- السطر 21: تتيح الدالة list تجميع المتغيرات في قائمة وتعيين قيمة لها بعملية تعيين واحدة. هنا $chaine1="chaine1" و $chaine2="chaine2".
- السطر 24: العلامة . هي علامة ربط السلاسل.
- السطر 88: الكلمة الرئيسية function تُعرّف دالة. تُرجع الدالة قيمًا أو لا تُرجعها بواسطة الأمر return. يمكن للكود المستدعي تجاهل نتائج الدالة أو استردادها. يمكن تعريف الدالة في أي مكان في الكود.
- السطر 90: الدالة المُعرَّفة مسبقًا getType($variable) تُرجع سلسلة أحرف تمثل نوع $variable. وقد يتغير هذا النوع بمرور الوقت.
- السطر 79: الدالة المُعرَّفة مسبقًا exit تُوقف تشغيل البرنامج النصي.
3.2. نطاق المتغيرات
3.2.1. البرنامج 1 (exemple_02)
<?php
// نطاق المتغيرات
function f1() {
// يتم استخدام المتغير العام $i
$i = &$GLOBALS["i"];
$i++;
$j = 10;
print "f1[i,j]=[$i,$j]\n";
}
function f2() {
// يتم استخدام المتغير العام $i
$i = &$GLOBALS["i"];
$i++;
$j = 20;
print "f2[i,j]=[$i,$j]\n";
}
function f3() {
// يتم استخدام متغير محلي $i
$i = 4;
$j = 30;
print "f3[i,j]=[$i,$j]\n";
}
// اختبارات
$i = 0;
$j = 0; // هاتان المتغيرتان معروفتان لدالة f عبر المصفوفة $GLOBALS
f1();
f2();
f3();
print "test[i,j]=[$i,$j]\n";
?>
النتائج:
تعليقات
- السطران 29-30: يحددان متغيرين $i و $j من البرنامج الرئيسي. هذه المتغيرات غير معروفة داخل الدوال. وبالتالي، في السطر 9، فإن المتغير $j الخاص بالدالة f1 هو متغير محلي للدالة f1 ويختلف عن المتغير $j في البرنامج الرئيسي. يمكن لدالة الوصول إلى متغير $variable في البرنامج الرئيسي عبر مصفوفة من المتغيرات العالمية تسمى $GLOBALS. في السطر 7، تشير الصيغة $GLOBALS["i"] إلى المتغير العام $i في البرنامج الرئيسي. إذا كتبنا
يتم تعيين قيمة المتغير العام $i إلى المتغير المحلي $i. وهنا لدينا متغيران مختلفان، ولن يؤدي تعديل المتغير المحلي $i إلى تغيير المتغير العام $i. الترميز
يجعل المتغير المحلي $i له نفس عنوان الذاكرة للمتغير العام $i. وبالتالي، فإن التعامل مع المتغير المحلي $i يعادل التعامل مع المتغير العام $i.
3.2.2. البرنامج 2 (exemple_03)
<?php
// نطاق المتغير شامل لجميع كتل الكود
$i = 0; {
$i = 4;
$i++;
}
print "i=$i\n";
?>
النتائج:
تعليقات
في بعض اللغات، يكون نطاق المتغير المُعرَّف داخل الأقواس المتعقبة هو نطاق هذه الأقواس: أي أنه غير معروف خارجها. تُظهر النتائج أعلاه أن الأمر ليس كذلك في لغة PHP. المتغير $i المُعرَّف في السطر 5 داخل الأقواس المتعقوفة هو نفسه المتغير المستخدم في السطرين 4 و8 خارجها.
3.3. الجداول
3.3.1. الجداول التقليدية أحادية البعد (exemple_04)
<?php
// المصفوفات التقليدية
// التعيين
$tab1 = array(0, 1, 2, 3, 4, 5);
// التجول - 1
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++)
print "tab1[$i]=$tab1[$i]\n";
// التجول - 2
print "tab1 a " . count($tab1) . " éléments\n";
reset($tab1);
while (list($clé, $valeur) = each($tab1))
print "tab1[$clé]=$valeur\n";
// إضافة عناصر
$tab1[] = $i++;
$tab1[] = $i++;
// التنقل - 3
print "tab1 a " . count($tab1) . " éléments\n";
$i = 0;
foreach ($tab1 as $élément) {
print "tab1[$i]=$élément\n";
$i++;
}
// حذف العنصر الأخير
array_pop($tab1);
// المسار - 4
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++)
print "tab1[$i]=$tab1[$i]\n";
// حذف العنصر الأول
array_shift($tab1);
// التنقل - 5
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++)
print "tab1[$i]=$tab1[$i]\n";
// إضافة في نهاية الجدول
array_push($tab1, -2);
// مسار - 6
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++)
print "tab1[$i]=$tab1[$i]\n";
// إضافة في بداية الجدول
array_unshift($tab1, -1);
// التنقل - 7
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++)
print "tab1[$i]=$tab1[$i]\n";
?>
النتائج:
تعليقات
يُظهر البرنامج أعلاه عمليات معالجة مصفوفة من القيم. توجد طريقتان لكتابة المصفوفات في PHP:
يُطلق على المصفوفة 1 اسم «مصفوفة»، أما المصفوفة 2 فتُسمى «قاموس» حيث تُدوّن العناصر على النحو التالي: المفتاح => القيمة. تشير الصيغة $contraires["beau"] إلى القيمة المرتبطة بالمفتاح "جميل". وهي هنا السلسلة "قبيح". المصفوفة 1 ليست سوى شكل آخر من أشكال القاموس ويمكن تدوينها على النحو التالي:
وبذلك نحصل على $tableau[2]="trois". في النهاية، لا يوجد سوى القواميس. في حالة مصفوفة تقليدية مكونة من n عنصرًا، تكون المفاتيح هي الأعداد الصحيحة من النطاق [0,n-1].
- السطر 15: تسمح الدالة each($tableau) بالتنقل عبر القاموس. وعند كل استدعاء، تُرجع زوجًا (مفتاح، قيمة) منه.
- السطر 14: تضع الدالة reset($dictionnaire) الدالة each على الزوج الأول (مفتاح، قيمة) من القاموس.
- السطر 15: تتوقف الحلقة while عندما تُرجع الدالة each زوجًا فارغًا عند نهاية القاموس.
- السطر 19: تضيف صيغة $tableau[]=قيمة العنصر valeur كآخر عنصر في $tableau.
- السطر 25: يتم تصفح المصفوفة باستخدام foreach. يسمح هذا العنصر النحوي بتصفح قاموس، وبالتالي مصفوفة، وفقًا لنظامين نحويين:
تُرجع الصيغة الأولى زوجًا (clé,valeur) في كل تكرار، بينما تُرجع الصيغة الثانية العنصر valeur من القاموس فقط.
- السطر 31: الدالة array_pop($tableau) تحذف العنصر الأخير من $tableau
- السطر 39: تقوم الدالة array_shift($tableau) بحذف العنصر الأول من $tableau
- السطر 47: تضيف الدالة array_push($tableau,قيمة) valeur كعنصر أخير في $tableau
- السطر 39: تضيف الدالة array_unshift($tableau، القيمة) valeur كأول عنصر في $tableau
3.3.2. القاموس (exemple_05)
<?php
// قواميس
$conjoints = array("Pierre" => "Gisèle", "Paul" => "Virginie", "Jacques" => "Lucette", "Jean" => "");
// مسار - 1
print "Nombre d'éléments du dictionnaire : " . count($conjoints) . "\n";
reset($conjoints);
while (list($clé, $valeur) = each($conjoints))
print "conjoints[$clé]=$valeur\n";
// فرز القاموس حسب المفتاح
ksort($conjoints);
// مسار - 2
reset($conjoints);
while (list($clé, $valeur) = each($conjoints))
print "conjoints[$clé]=$valeur\n";
// قائمة مفاتيح القاموس
$clés = array_keys($conjoints);
for ($i = 0; $i < count($clés); $i++)
print "clés[$i]=$clés[$i]\n";
// قائمة قيم القاموس
$valeurs = array_values($conjoints);
for ($i = 0; $i < count($valeurs); $i++)
print "valeurs[$i]=$valeurs[$i]\n";
// البحث عن مفتاح
existe($conjoints, "Jacques");
existe($conjoints, "Lucette");
existe($conjoints, "Jean");
// حذف مفتاح وقيمة
unset($conjoints["Jean"]);
print "Nombre d'éléments du dictionnaire : " . count($conjoints) . "\n";
foreach ($conjoints as $clé => $valeur) {
print "conjoints[$clé]=$valeur\n";
}
// النهاية
exit;
function existe($conjoints, $mari) {
// التحقق من وجود المفتاح $mari في القاموس $conjoints
if (isset($conjoints[$mari]))
print "La clé [$mari] existe associée à la valeur [$conjoints[$mari]]\n";
else
print "La clé [$mari] n'existe pas\n";
}
?>
النتائج:
تعليقات
يطبق الكود السابق على القاموس ما سبق أن تناولناه سابقًا بالنسبة لمصفوفة بسيطة. وسنكتفي بالتعليق على العناصر الجديدة فقط:
- السطر 13: تتيح الدالة ksort (فرز حسب المفتاح) فرز القاموس حسب الترتيب الطبيعي للمفتاح.
- السطر 21: تعرض الدالة array_keys($dictionnaire) قائمة مفاتيح القاموس في شكل جدول
- السطر 26: تعرض الدالة array_values($dictionnaire) قائمة قيم القاموس في شكل مصفوفة
- السطر 47: تعرض الدالة isset($variable) القيمة true إذا تم تعريف المتغير $variable، وإلا تعرض القيمة false.
- السطر 36: الدالة unset($variable) تحذف المتغير $variable.
3.3.3. المصفوفات متعددة الأبعاد (exemple_06)
<?php
// الجداول التقليدية متعددة الأبعاد
// التهيئة
$multi = array(array(0, 1, 2), array(10, 11, 12, 13), array(20, 21, 22, 23, 24));
// التصفح
for ($i1 = 0; $i1 < count($multi); $i1++)
for ($i2 = 0; $i2 < count($multi[$i1]); $i2++)
print "multi[$i1][$i2]=" . $multi[$i1][$i2] . "\n";
// قواميس متعددة الأبعاد
// التهيئة
$multi = array("zéro" => array(0, 1, 2), "un" => array(10, 11, 12, 13), "deux" => array(20, 21, 22, 23, 24));
// التصفح
foreach ($multi as $clé => $valeur)
for ($i2 = 0; $i2 < count($valeur); $i2++)
print "multi[$clé][$i2]=" . $multi[$clé][$i2] . "\n";
?>
النتائج:
تعليقات
- السطر 5: عناصر المصفوفة $multi هي نفسها مصفوفات
- السطر 12: يصبح المصفوفة $multi قاموسًا (clé,valeur) حيث كل valeur هو مصفوفة
3.3.4. الروابط بين السلاسل والجداول (exemple_07)
<?php
// تحويل سلسلة إلى مصفوفة
$chaine = "1:2:3:4";
$tab = explode(":", $chaine);
// التنقل في المصفوفة
print "tab a " . count($tab) . " éléments\n";
for ($i = 0; $i < count($tab); $i++)
print "tab[$i]=$tab[$i]\n";
// مصفوفة إلى سلسلة
$chaine2 = implode(":", $tab);
print "chaine2=$chaine2\n";
// إضافة حقل فارغ
$chaine.=":";
print "chaîne=$chaine\n";
$tab = explode(":", $chaine);
// تجول في المصفوفة
print "tab a " . count($tab) . " éléments\n";
for ($i = 0; $i < count($tab); $i++)
print "tab[$i]=$tab[$i]\n"; // لدينا الآن 5 عناصر، آخرها فارغ
// لنضف حقلًا فارغًا مرة أخرى
$chaine.=":";
print "chaîne=$chaine\n";
$tab = explode(":", $chaine);
// التنقل عبر المصفوفة
print "tab a " . count($tab) . " éléments\n";
for ($i = 0; $i < count($tab); $i++)
print "tab[$i]=$tab[$i]\n"; // لدينا الآن 6 عناصر، وآخر عنصرين فارغان
?>
النتائج:
تعليقات
- السطر 5: تسمح الدالة explode($séparateur,$chaine) باسترداد حقول $chaine المفصولة بـ $séparateur. وبالتالي، تسمح الدالة explode(":",$chaine) باسترداد عناصر $chaine المفصولة بالسلسلة ":" في شكل مصفوفة.
- أما الدالة implode($séparateur,$tableau) فتقوم بالعملية المعاكسة للدالة explode. فهي تُرجع سلسلة أحرف مكونة من عناصر $tableau المفصولة بـ $séparateur.
3.4. سلاسل الأحرف
3.4.1. الترميز (exemple_08)
<?php
// تدوين السلاسل
$chaine1 = "un";
$chaine2 = 'un';
print "[$chaine1,$chaine2]\n";
?>
النتائج:
3.4.2. المقارنة (exemple_09)
<?php
// اختبارات مقارنة السلاسل
compare("abcd", "abcd");
compare("", "");
compare("1", "");
exit;
function compare($chaine1, $chaine2) {
// مقارنة السلسلة 1 بالسلسلة 2
if ($chaine1 == $chaine2)
print "[$chaine1] est égal à [$chaine2]\n";
else
print "[$chaine1] est différent de [$chaine2]\n";
}
?>
النتائج:
3.5. التعبيرات العادية (exemple_10)
<?php
// التعبيرات النمطية في PHP
// استرداد الحقول المختلفة لسلسلة
// النمط: سلسلة من الأرقام محاطة بأي أحرف
// نريد استخراج سلسلة الأرقام فقط
$modèle = "/(\d+)/";
// مقارنة السلسلة بالنموذج
compare($modèle, "xyz1234abcd");
compare($modèle, "12 34");
compare($modèle, "abcd");
// النموذج: سلسلة من الأرقام محاطة بأي أحرف
// نريد سلسلة الأرقام بالإضافة إلى الحقول التي تليها وتسبقها
$modèle = "/^(.*?)(\d+)(.*?)$/";
// نقوم بمقارنة السلسلة بالنموذج
compare($modèle, "xyz1234abcd");
compare($modèle, "12 34");
compare($modèle, "abcd");
// القالب - تاريخ بتنسيق يوم/شهر/سنة
$modèle = "/^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$/";
compare($modèle, "10/05/97");
compare($modèle, " 04/04/01 ");
compare($modèle, "5/1/01");
// القالب - رقم عشري
$modèle = "/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/";
compare($modèle, "187.8");
compare($modèle, "-0.6");
compare($modèle, "4");
compare($modèle, ".6");
compare($modèle, "4.");
compare($modèle, " + 4");
// النهاية
exit;
// --------------------------------------------------------------------------
function compare($modèle, $chaîne) {
// يقارن السلسلة $chaîne بالنموذج $modèle
// مقارنة السلسلة بالنموذج
$correspond = preg_match($modèle, $chaîne, $champs);
// عرض النتائج
print "\nRésultats($modèle,$chaîne)\n";
if ($correspond) {
for ($i = 0; $i < count($champs); $i++)
print "champs[$i]=$champs[$i]\n";
} else
print "La chaîne [$chaîne] ne correspond pas au modèle [$modèle]\n";
}
?>
النتائج:
تعليقات
- السطران 3-4: نستخدم هنا التعبيرات النمطية لاستخراج الحقول المختلفة من سلسلة أحرف. تتيح التعبيرات النمطية تجاوز حدود الدالة implode. المبدأ هو مقارنة سلسلة أحرف بسلسلة أخرى تسمى modèle باستخدام الدالة preg_match:
$correspond = preg_match($modèle, $chaîne, $champs);
تُرجع الدالة preg_match قيمة منطقية إذا كان من الممكن العثور على modèle في chaîne. إذا كان الأمر كذلك، فإن $champs[0] تمثل السلسلة الفرعية المطابقة للنموذج. من ناحية أخرى، إذا كان النموذج يحتوي على نماذج فرعية بين قوسين، فإن $champs[1] هو الجزء من $chaîne المطابق للنموذج الفرعي الأول، و $champs[2] هو الجزء من $chaîne الذي يتوافق مع النموذج الفرعي الثاني، وهكذا دواليك...
لنأخذ المثال الأول. يتم تعريف النموذج في السطر 8: وهو يشير إلى سلسلة من رقم واحد أو أكثر (+) من الأرقام (\d) موضوعة في أي مكان في السلسلة. علاوة على ذلك، يحدد النموذج نموذجًا فرعيًا محاطًا بأقواس.
- السطر 10: يتم مقارنة النموذج /(\d+)/ (سلسلة من رقم واحد أو أكثر في أي مكان في السلسلة) بالسلسلة "xyz1234abcd". نرى أن السلسلة الفرعية 1234 تتطابق مع النموذج. وبالتالي، سيكون $champs[0] مساويًا لـ "1234". من ناحية أخرى، يحتوي النمط على أنماط فرعية بين الأقواس. فسنحصل على $champs[1] = "1234".
- السطر 11: يتم مقارنة النمط /(\d+)/ بالسلسلة "12 34". نلاحظ أن السلسلتين الفرعيتين 12 و34 تتطابقان مع النمط. تتوقف المقارنة عند أول سلسلة فرعية تتطابق مع النمط. وبالتالي، سيكون لدينا $champs[0]=12 و $champs[1]=12.
- السطر 12: يتم مقارنة النمط /(\d+)/ بالسلسلة "abcd". لم يتم العثور على أي تطابق.
دعونا نوضح الأنماط المستخدمة في بقية الكود:
$modèle = "/^(.*?)(\d+)(.*?)$/";
بداية السلسلة (^)، ثم صفر أو أكثر (*) من الأحرف العشوائية (.)، ثم رقم واحد أو أكثر (+)، ثم مرة أخرى صفر أو أكثر (*) من الأحرف العشوائية (.). يشير النمط (.*) إلى صفر أو أكثر من الأحرف العشوائية. سيتطابق هذا النمط مع أي سلسلة. وبالتالي، لن يتم العثور أبدًا على النمط /^(.*)(\d+)(.*)$/ لأن النمط الفرعي الأول (.*) سيستوعب السلسلة بأكملها. أما النمط (.*?)(\d+) فيشير إلى صفر أو أكثر من الأحرف العشوائية حتى النمط الفرعي التالي (؟)، وهو هنا \d+. وبالتالي، لم تعد الأرقام تُستوعب الآن بواسطة النمط (.*). وبالتالي، فإن النمط أعلاه يتطابق مع [début de chaîne (^), une suite de caractères quelconques (.*?), une suite d'un ou plusieurs chiffres (\d+), une suite de caractères quelconques (.*?), la fin de la chaîne ($)].
$modèle = "/^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$/";
يتطابق مع [début de chaîne (^), 2 chiffres (\d\d), le caractère / (\/), 2 chiffres, /, 2 chiffres, une suite de 0 ou plusieurs espaces (\s*), la fin de chaîne ($)]
$modèle = "/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/";
[début de chaîne (^), 0 ou plusieurs espaces (\s*), un signe + ou - [+|-] présent 0 ou 1 fois (?), une suite de 0 ou plusieurs espaces (\s*), 1 ou plusieurs chiffres suivis d'un point décimal suivi de zéro ou plusieurs chiffres (\d+\.\d*) ou (|) un point décimal (\.) suivi d'un ou plusieurs chiffres (\d+) ou (|) un ou plusieurs chiffres (\d+), une suite de 0 ou plusieurs espaces (\s*)].
3.6. طريقة تمرير معلمات الدوال (exemple_11)
<?php
// طريقة تمرير المعلمات
function f(&$i, $j) {
// سيتم الحصول على $i بالرجوع إلى النموذج
// سيتم الحصول على $j بالقيمة
$i++;
$j++;
print "f[i,j]=[$i,$j]\n";
}
// ----------------------------------------اختبارات
$i = 0;
$j = 0;
// تم تمرير $i و $j بالقيمة
f($i, $j);
print "test[i,j]=[$i,$j]\n";
?>
النتائج:
تعليقات
يُظهر الكود أعلاه طريقتين لتمرير المعلمات إلى دالة. لنأخذ المثال التالي:
- السطر 1: يحدد المعلمات الشكلية $a و $b للدالة f. تقوم هذه الدالة بمعالجة هذين المعلمتين الشكليتين وتُرجع نتيجة.
- السطر 7: استدعاء الدالة f بمعلمتين فعليتين هما $i و $j. يتم تحديد الروابط بين المعلمات الشكلية ($a، $b) والمعلمات الفعلية ($i، $j) في السطر 7
- &$a: تشير علامة & إلى أن المعلمة الشكلية $a ستأخذ كقيمة عنوان المعلمة الفعلية $i. بعبارة أخرى، $a و $i هما مرجعان لنفس موقع الذاكرة. إن التعامل مع المعلمة الشكلية $a يعادل التعامل مع المعلمة الفعلية $i. وهذا ما يظهره تنفيذ الكود. يناسب هذا النمط من التمرير معلمات الإخراج والبيانات الضخمة مثل المصفوفات والقواميس. ويُطلق على هذا النمط من التمرير اسم «التمرير بالمرجع».
- $b: ستتخذ المعلمة الشكلية $b القيمة نفسها التي تتخذها المعلمة الفعلية $j. وهذا يمثل تمريرًا بالقيمة. المعلمات الشكلية والفعلية هما متغيران مختلفان. ولا يؤثر التعامل مع المعلمة الشكلية $b بأي شكل من الأشكال على المعلمة الفعلية $j. وهذا ما يوضحه تنفيذ الكود. ويناسب هذا النمط من التمرير معلمات الإدخال.
- لنفترض أن الدالة échange تقبل معلمتين شكليتين هما $a و $b. تقوم الدالة بتبديل قيمة هذين المعلمتين. وبالتالي، عند إجراء استدعاء تبديل ($i,$j)، يتوقع الكود المستدعي أن يتم تبديل قيم المعلمتين الفعليتين. وبالتالي فهما معلمتان مخرجات (يتم تعديلهما). لذا سنكتب:
3.7. النتائج التي ترجعها الدالة (exemple_12)
<?php
// النتائج التي تعطيها الدالة
// يمكن للدالة أن تُرجع عدة قيم في صفيفة
list($res1, $res2, $res3) = f1(10);
print "[$res1,$res2,$res3]\n";
$res = f1(10);
for ($i = 0; $i < count($res); $i++)
print "res[$i]=$res[$i]\n";
// يمكن للدالة أن ترجع كائنًا زائفًا
$res = f2(10);
print "[$res->res1,$res->res2,$res->res3]\n";
// نهاية
exit;
// الدالة f1
function f1($valeur) {
// تُرجع مصفوفة ($valeur+1,$aleur+2,$baleur+3)
return array($valeur + 1, $valeur + 2, $valeur + 3);
}
// الدالة f2
function f2($valeur) {
// تُرجع كائنًا زائفًا ($valeur+1,$aleur+2,$baleur+3)
$res->res1 = $valeur + 1;
;
$res->res2 = $valeur + 2;
$res->res3 = $valeur + 3;
// يعرض الكائن
return $res;
}
?>
النتائج
تعليقات
- يوضح البرنامج السابق أن الدالة PHP يمكنها إرجاع مجموعة من النتائج وليس نتيجة واحدة، في شكل مصفوفة أو كائن. وسيتم توضيح مفهوم الكائن لاحقًا
- الأسطر 19-22: تُرجع الدالة f1 عدة قيم في شكل مصفوفة
- الأسطر 25-33: تُرجع الدالة f2 عدة قيم في شكل كائن
3.8. الملفات النصية (exemple_13)
<?php
// استغلال متسلسل لملف نصي
// وهو عبارة عن مجموعة من الأسطر بالشكل login:pwd:uid:gid:infos:dir:shell
// يتم وضع كل سطر في قاموس بالصيغة login => uid:gid:infos:dir:shell
// يتم تحديد اسم الملف
$INFOS = "infos.txt";
// يتم فتحه لإنشائه
if (!$fic = fopen($INFOS, "w")) {
print "Erreur d'ouverture du fichier $INFOS en écriture\n";
exit;
}
// يتم إنشاء محتوى عشوائي
for ($i = 0; $i < 100; $i++)
fputs($fic, "login$i:pwd$i:uid$i:gid$i:infos$i:dir$i:shell$i\n");
// يتم إغلاق الملف
fclose($fic);
// يتم استغلاله - تحافظ fgets على علامة نهاية السطر
// وهذا يمنع استرداد سلسلة فارغة عند قراءة سطر فارغ
// يتم فتحه لكتابة البيانات
if (!$fic = fopen($INFOS, "r")) {
print "Erreur d'ouverture du fichier $INFOS en lecture\n";
exit;
}
while ($ligne = fgets($fic, 1000)) {
// نحذف علامة نهاية السطر إن وجدت
$ligne = cutNewLineChar($ligne);
// نضع السطر في مصفوفة
$infos = explode(":", $ligne);
// يتم استرداد اسم المستخدم
$login = array_shift($infos);
// تجاهل كلمة المرور
array_shift($infos);
// يتم إنشاء إدخال في القاموس
$dico[$login] = $infos;
}
// نغلقه
fclose($fic);
// استغلال القاموس
afficheInfos($dico, "login10");
afficheInfos($dico, "X");
// النهاية
exit;
// --------------------------------------------------------------------------
function afficheInfos($dico, $clé) {
// عرض القيمة المرتبطة بالمفتاح في القاموس $dico إذا كانت موجودة
if (isset($dico[$clé])) {
// القيمة موجودة - هل هي مصفوفة؟
$valeur = $dico[$clé];
if (is_array($valeur)) {
print "[$clé," . join(":", $valeur) . "]\n";
} else {
// $valeur ليس مصفوفة
print "[$clé,$valeur]\n";
}
} else {
// $clé ليس مفتاحًا في القاموس $dico
print "la clé [$clé] n'existe pas\n";
}
}
// --------------------------------------------------------------------------
function cutNewLinechar($ligne) {
// يتم حذف علامة نهاية السطر من $ligne إن وجدت
$L = strlen($ligne); // طول السطر
while (substr($ligne, $L - 1, 1) == "\n" or substr($ligne, $L - 1, 1) == "\r") {
$ligne = substr($ligne, 0, $L - 1);
$L--;
}
// النهاية
return($ligne);
}
?>
الملف infos.txt:
login0:pwd0:uid0:gid0:infos0:dir0:shell0
login1:pwd1:uid1:gid1:infos1:dir1:shell1
login2:pwd2:uid2:gid2:infos2:dir2:shell2
...
login98:pwd98:uid98:gid98:infos98:dir98:shell98
login99:pwd99:uid99:gid99:infos99:dir99:shell99
النتائج:
تعليقات
- السطر 11: fopen(nom_fichier,"w") يفتح الملف nom_fichier في وضع الكتابة (w=write). إذا لم يكن الملف موجودًا، يتم إنشاؤه. وإذا كان موجودًا، يتم مسحه. وإذا فشل الإنشاء، فإن fopen تُرجع القيمة false. في العبارة if (!$fic = fopen($INFOS, "w")) {…}، توجد عمليتان متتاليتان: 1) $fic=fopen(..) 2) if( ! $fic) {...}
- السطر 18: fputs($fic,$chaîne) يكتب chaîne في الملف $fic.
- السطر 20: fclose($fic) يغلق الملف $fic.
- السطر 25: fopen(nom_fichier,"r") يفتح الملف nom_fichier للقراءة (r=read). إذا فشل فتح الملف (الملف غير موجود)، فإن fopen تُرجع القيمة false.
- السطر 29: fgets($fic,1000) يقرأ السطر التالي من الملف بحد أقصى 1000 حرف. في العملية while ($ligne = fgets($fic, 1000)) {…}، هناك عمليتان متتاليتان 1) $ligne=fgets(...) 2) while ( ! $ligne). بعد قراءة الحرف الأخير من الملف، تُفرغ الدالة fgets السلسلة وتتوقف الحلقة while.
- السطر 31: تقرأ الدالة fgets سطرًا من النص، بما في ذلك حرف نهاية السطر. تقوم الدالة cutNewLineChar في الأسطر 70-79 بإزالة حرف نهاية السطر إن وجد.
- السطر 72: تعرض الدالة strlen($chaîne) عدد أحرف $chaîne.
- السطر 73: الدالة substr($ligne, $position, $taille) تُرجع $taille حرفًا من $ligne، بدءًا من الحرف رقم $position، حيث يُعتبر الحرف الأول هو رقم 0. على أجهزة ويندوز، علامة نهاية السطر هي "\r\n". على أجهزة يونكس، هي السلسلة "\n".
- السطر 35: الدالة array_shift($tableau) تحذف العنصر الأول من $tableau وتعيّنه كنتيجة.
- السطر 37: يتم استخدام الدالة array_shift($tableau) ولكن يتم تجاهل نتيجتها
- السطر 57: تُرجع الدالة is_array($variable) القيمة true إذا كانت $variable مصفوفة، وإلا تُرجع false.
- السطر 58: الدالة join تقوم بنفس الشيء الذي تقوم به الدالة implode التي سبق أن تناولناها