1.4الدوال ونطاق المتغيرات
الأساسي في 30 ثانية
- الدالة = مدخلات ← معالجة ← مخرج : function nom($params) { return ... } — وسائط صريحة ونتيجة مردودة.
- نطاق محلي ولا عموميات : فمتغير داخلي غير مرئي في الخارج (والعكس) — ويُمرَّر كل شيء في الوسائط.
- نمّط في PHP الحديث : function f(int $a): int (مع strict_types) — يوثّق ويكشف الأخطاء ويقوّي.
حالة مستمرة — رياد يوحّد عروض أسعاره في قسنطينة
يحسب رياد السعر شامل الضريبة في ثلاثة مواضع من موقعه بالنسخ واللصق نفسه — وحين تغيّر المعدل نسي موضعا : فصار عرض من ثلاثة خاطئا. فأنشأ دالة prixTTC($ht, $taux = 0.19) منمّطة، تستقبل كل شيء في الوسائط وتردّ النتيجة : فصار موضع واحد للتصحيح. ولاحظ عرضا أن متغير $total المعرّف في الدالة غير موجود في الخارج — فالنطاق المحلي يلزمه بالردّ النظيف. فعادت العروض الثلاثة صحيحة دفعة واحدة.
تتمة الحالة 1.1-1.3 — ينتقل رياد من التكرار إلى إعادة الاستعمال.
1. تعريف دالة واستدعاؤها
الدالة (fonction) كتلة شيفرة قابلة لإعادة الاستعمال. تُعرَّف بـ function وتُستدعى باسمها : function saluer($nom) { return 'Bonjour ' . $nom; } ثم saluer('Alice'). والوسائط (paramètres) هي المدخلات ؛ وreturn يردّ المخرج. وقد تكون وسائط افتراضية ($nom = 'inconnu'). وتتفادى الدوال التكرار، وتحسّن المقروئية والصيانة والاختبار.
يستبدل رياد نسخه الثلاث للصق حساب شامل الضريبة باستدعاء prixTTC(10000) : فيُطبق المعدل الافتراضي، وتمرّر حالة خاصة معدلها الخاص.
2. النطاق والتنميط
النطاق (scope) : فالمتغير المعرّف داخل دالة محلي (غير مرئي في الخارج) ؛ والمتغير الخارجي غير متاح في الداخل. عزل مقصود — وتُمرَّر المعطيات في الوسائط (وليس عبر العموميات). ويشجّع PHP الحديث التنميط (typage) : function additionner(int $a, int $b): int يوثّق ويلتقط أخطاء ويقوّي. واعرف أيضا : المغلَّفات (closures) أي الدوال المجهولة، ومئات الدوال الأصلية — فلا تعِد الاختراع واستشر التوثيق.
ينمّط رياد دالته بـ (float $ht, float $taux = 0.19): float مع declare(strict_types=1) : فالنوع الخاطئ يثير خطأ واضحا بدلا من عرض سعر خاطئ بصمت.
🔎 مثال ملموس — 🔎 مثال ملموس — دالة منمّطة
مدخلات ومخرج واضحان، كما فعل رياد لعروضه.
declare(strict_types=1);
function prixTTC(float $ht, float $taux = 0.20): float {
return $ht * (1 + $taux);
}
echo prixTTC(100); // 120
echo prixTTC(100, 0.055); // 105.5
القراءة : وسائط منمّطة وافتراضي للمعدل الجاري وردّ منمّط — فتُقرأ الواجهة دون فتح الجسم.
الدرس : declare(strict_types=1) لتنميط صارم — دالة قابلة لإعادة الاستعمال وموثِّقة ذاتيا.
مفردات القسم
- الدالة
- كتلة شيفرة قابلة لإعادة الاستعمال تنجز مهمة : function saluer($nom) { return ... }، وتُستدعى باسمها. تتفادى التكرار وتحسّن المقروئية والصيانة.
مثال بسيط: prixTTC($ht, $taux) الوحيدة لرياد، المستدعاة ثلاث مرات.
ما ليس كذلك: الحساب نفسه منسوخا ملصقا في ثلاثة مواضع.
رد فعل: حساب تكرر مرتين = دالة.
- الوسائط / الردّ
- الوسائط : معطيات تُمرَّر مدخلا (مع قيم افتراضية ممكنة). والردّ (عبر return) : النتيجة المردودة. وهما مدخلات الدالة ومخرجاتها.
مثال بسيط: $ht و$taux لرياد، والمجموع شامل الضريبة المردود.
ما ليس كذلك: قراءة عمومية وتعديل متغير خارجي.
رد فعل: كل شيء يدخل بالوسائط ويخرج بـ return.
- النطاق (scope)
- المتغير المعرّف في دالة محلي (غير مرئي في الخارج) ؛ والمتغير الخارجي غير متاح في الدالة. عزل مقصود — وتُمرَّر المعطيات في الوسائط.
مثال بسيط: $total الداخلي لرياد، غير المرئي من الخارج.
ما ليس كذلك: الوصول إلى عمومية عبر الكلمة global.
رد فعل: تحتاج معلومة ؟ وسيط وليست عمومية.
- تنميط الوسائط/الردّ
- إعلان الأنواع (function f(int $a): int) يوثّق ويلتقط أخطاء ويقوّي الشيفرة — موصى به بشدة في PHP الحديث.
مثال بسيط: (float $ht, float $taux): float لرياد.
ما ليس كذلك: سعر ممرَّر نصا يُفسد عرض السعر بصمت.
رد فعل: نمّط الوسائط والردّ وفعّل الصارم.
- المغلَّفات / الدوال الأصلية
- دوال مجهولة (closures) وسهمية : دون اسم، تُخزَّن/تُمرَّر (callbacks). ولـ PHP مئات الدوال الأصلية (strlen وarray_map…) — فاستشر التوثيق.
مثال بسيط: رياد يرتّب بـ usort وسهمية بدلا من برمجة ترتيبه.
ما ليس كذلك: إعادة كتابة يدوية لدالة أصلية موجودة.
رد فعل: ابحث عن الأصلية قبل البرمجة.
في التطبيق — تطبيقيا — اكتب دوال قابلة لإعادة الاستعمال
- عرّف دالة بـ `function` ووسائط و`return` (مثلا حساب سعر شامل الضريبة من سعر دون ضريبة).
- أضف وسيطا افتراضيا وجرّب الاستدعاء معه ودونه.
- لاحظ النطاق : فالمتغير المعرّف في الدالة غير موجود في الخارج ؛ ومرّر المعطيات الخارجية في الوسائط (وليس عبر العموميات).
- أضف تنميط الوسائط والردّ (`function f(int $a, int $b): int`) واكتشف بعض الدوال الأصلية (strlen وcount وarray_map).
نص جاهز للنطق — ارفض العمومية في مراجعة الشيفرة (30 ث)
« أقترح تمرير هذه المعلومة في وسيط بدلا من عمومية : فالتوقيع سيقول ما تنتظره الدالة، وتبقى متوقعة وقابلة للاختبار. فالعموميات تخلق تبعيات خفية — ومن هناك سيأتي الخلل التالي. »
يُقال في مراجعة الشيفرة ؛ واعرض التوقيع قبل/بعد.
نموذج نسخ ولصق — دالة منمّطة prixTTC (وسائط + افتراضي + return)
عرض سعر في قسنطينة
كما فعل رياد : دالة واحدة منمّطة prixTTC — فحين يتغير المعدل، سطر واحد للتصحيح وثلاثة عروض صحيحة.
معلومة خارجية للاستعمال
مرّرها في وسيط صريح : فالتوقيع يوثّق الحاجة، وتبقى الدالة قابلة للاختبار معزولة.
قيمة افتراضية
المعدل الجاري افتراضيا ($taux = 0.19) : فالاستدعاء البسيط يغطي الحالة الجارية، والاستدعاء الكامل الحالة الخاصة.
ترتيب أو تحويل
مغلَّفة أو سهمية لـ usort/array_map : فالمعالجة الظرفية تتسع في سطر واحد، دون دالة مسماة مخصصة.
✓ ممارسات جيدة
- مرّر المعطيات في الوسائط وردّ النتيجة (لا عموميات).
- نمّط الوسائط والردّ (declare(strict_types=1)).
- ابحث عن دالة أصلية قبل البرمجة يدويا.
✗ أخطاء شائعة
- استعمال المتغيرات العمومية (تبعيات خفية وآثار جانبية).
- كتابة دالة عملاقة متعددة المسؤوليات.
- إعادة اختراع دالة أصلية موجودة.
النقاط الأساسية
- الدوال كتل قابلة لإعادة الاستعمال (وسائط مدخلا وRETURN مخرجا) : تتفادى التكرار وتحسّن المقروئية والصيانة والاختبار.
- النطاق : فالمتغير المعرّف في دالة محلي ؛ والمتغيرات الخارجية غير متاحة في الداخل (عزل) — ومرّر المعطيات في الوسائط.
- في PHP الحديث : نمّط الوسائط والردّ (`function f(int $a): int`) فذلك يوثّق ويلتقط أخطاء ويقوّي.
- المغلَّفات للـ callbacks ؛ ومئات الدوال الأصلية — فاستشر التوثيق ولا تعِد الاختراع. والتقطيع الجيد = شيفرة قابلة للصيانة.
تحدي 48 ساعة — طبّق غدا
استخرج حسابا مكررا من شيفرتك في دالة منمّطة (النموذج أعلاه) : وسائط صريحة وreturn وstrict_types. واستدعها في المواضع القديمة وتحقق من النتائج. تكفي 25 دقيقة.
- أعرّف دوال بوسائط وافتراضي وreturn وأنواع.
- أحترم النطاق المحلي — ولا عموميات.
- أبحث عن الدالة الأصلية قبل البرمجة يدويا.
أسئلة شائعة
لماذا تُمرَّر المعطيات في الوسائط بدلا من المتغيرات العمومية ؟
في PHP، المتغير المعرّف في دالة محلي، والمتغير الخارجي غير متاح فيها (عزل مقصود). ويمكن استعمال الكلمة `global`، لكنها ممارسة سيئة : اقتران خفي (فلا شيء في التوقيع يدل على التبعية) وآثار جانبية لا تُتوقع (تعديلات عن بعد) وصعوبة في الاختبار وإعادة استعمال محدودة. والتمرير في الوسائط يعطي : واجهة صريحة وتوقعا (المدخلات نفسها = الناتج نفسه) وقابلية اختبار وفصلا. وللإعداد المشترك استعمل مقاربات نظيفة (حقن التبعيات والخدمات) بدلا من العموميات.
هل يجب تنميط الوسائط والمردودات في PHP، وماذا يفيد ذلك ؟
نعم، موصى به بشدة في PHP الحديث. ويفيد التنميط : (1) كشف الأخطاء — فالنوع الخاطئ يثير خطأ واضحا عند الاستدعاء (خصوصا في الصارم) ؛ (2) توثيقا ضمنيا — فالأنواع تصف الواجهة دون قراءة الجسم ؛ (3) أدوات أفضل — إكمال تلقائي وتحليل ساكن وإعادة هيكلة آمنة ؛ (4) قوة. فعّل `declare(strict_types=1);` وحوّل صراحة عند الحاجة. بتكلفة ضئيلة وفوائد مهمة.
كيف يجب أن تستقبل الدالة المعطيات التي تحتاجها ؟