1.4 · الدوال ونطاق المتغيرات

المستوى 1 · أساسيات اللغة

1.4الدوال ونطاق المتغيرات

الهدف: كتابة دوال قابلة لإعادة الاستعمال (الوسائط والردّ والقيم الافتراضية والتنميط)، وفهم نطاق المتغيرات، وتقطيع شيفرتك بنظافة.
الوقت المقدّر: 11 دقيقة · قراءة ذاتية · إذا كان لديك 5 دقائق فقط: اقرأ «الأساسي في 30 ثانية» + المخطط.

الأساسي في 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) : فالنوع الخاطئ يثير خطأ واضحا بدلا من عرض سعر خاطئ بصمت.

خطأ شائع في الفهم: « ترى الدالة المتغيرات الخارجية » أو « التنميط للزينة فقط ». لا. ففي PHP لا يدخل الخارج إلى الدالة : فالمتغير العام غير متاح فيها (وهذا مقصود) — ويمرّ كل شيء في الوسائط، ويخرج الناتج بـ return. والتنميط ليس زخرفة : فهو يحوّل أخطاء صامتة إلى أخطاء واضحة عند الاستدعاء، ويوثّق الواجهة ويساعد المحرر — بتكلفة ضئيلة وفوائد كبرى.
دالة مدخلات ← معالجة ← مخرج الوسائط المدخلات(منمّطة)المعالجة شيفرة محليةمعزولة (نطاق)return المخرج المردود
مدخلات ← معالجة ← مخرج
نص المخطط (SEO / قارئات الشاشة / الترجمة): 1) عرّف : يكتب رياد function prixTTC($ht, $taux = 0.19) مرة واحدة بدلا من ثلاث نسخ ملصقة. 2) اعزل : فالمتغيرات الداخلية محلية — وكل شيء يدخل بالوسائط ويخرج بـ return، ولا عموميات. 3) نمّط : (float ...): float مع strict_types، وخطأ واضح عند النوع الخاطئ. الدرس : الدالة = واجهة صريحة وفضاء معزول وأنواع معلنة.

🔎 مثال ملموس — 🔎 مثال ملموس — دالة منمّطة

مدخلات ومخرج واضحان، كما فعل رياد لعروضه.

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 وسهمية بدلا من برمجة ترتيبه.

ما ليس كذلك: إعادة كتابة يدوية لدالة أصلية موجودة.

رد فعل: ابحث عن الأصلية قبل البرمجة.

في التطبيق — تطبيقيا — اكتب دوال قابلة لإعادة الاستعمال

  1. عرّف دالة بـ `function` ووسائط و`return` (مثلا حساب سعر شامل الضريبة من سعر دون ضريبة).
  2. أضف وسيطا افتراضيا وجرّب الاستدعاء معه ودونه.
  3. لاحظ النطاق : فالمتغير المعرّف في الدالة غير موجود في الخارج ؛ ومرّر المعطيات الخارجية في الوسائط (وليس عبر العموميات).
  4. أضف تنميط الوسائط والردّ (`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 وأنواع.
  • أحترم النطاق المحلي — ولا عموميات.
  • أبحث عن الدالة الأصلية قبل البرمجة يدويا.
تقييم ذاتي 1-5 : هل تستقبل دوالي كل شيء في الوسائط ؟هل وسائطي ومردوداتي منمّطة ؟

أسئلة شائعة

لماذا تُمرَّر المعطيات في الوسائط بدلا من المتغيرات العمومية ؟

في PHP، المتغير المعرّف في دالة محلي، والمتغير الخارجي غير متاح فيها (عزل مقصود). ويمكن استعمال الكلمة `global`، لكنها ممارسة سيئة : اقتران خفي (فلا شيء في التوقيع يدل على التبعية) وآثار جانبية لا تُتوقع (تعديلات عن بعد) وصعوبة في الاختبار وإعادة استعمال محدودة. والتمرير في الوسائط يعطي : واجهة صريحة وتوقعا (المدخلات نفسها = الناتج نفسه) وقابلية اختبار وفصلا. وللإعداد المشترك استعمل مقاربات نظيفة (حقن التبعيات والخدمات) بدلا من العموميات.

هل يجب تنميط الوسائط والمردودات في PHP، وماذا يفيد ذلك ؟

نعم، موصى به بشدة في PHP الحديث. ويفيد التنميط : (1) كشف الأخطاء — فالنوع الخاطئ يثير خطأ واضحا عند الاستدعاء (خصوصا في الصارم) ؛ (2) توثيقا ضمنيا — فالأنواع تصف الواجهة دون قراءة الجسم ؛ (3) أدوات أفضل — إكمال تلقائي وتحليل ساكن وإعادة هيكلة آمنة ؛ (4) قوة. فعّل `declare(strict_types=1);` وحوّل صراحة عند الحاجة. بتكلفة ضئيلة وفوائد مهمة.

تحقّق من فهمك

كيف يجب أن تستقبل الدالة المعطيات التي تحتاجها ؟

موارد إضافية (اختياري، للتعمّق أكثر)

اختبار المستوى 1أسئلة جديدة وأصعب للتحقق من مكتسباتك