2.3التضمينات (Inclusions) والتنظيم وإدارة الملفات
الأساسي في 30 ثانية
- اكتب مرة وضمِّن في كل مكان : الترويسة والتذييل والإعداد والدوال تعيش في ملفات مخصصة تُجمَّع بـ require/include — صفر تكرار.
- require للضروري : require يفشل بخطأ قاتل إن غاب الملف (الإعداد، الدوال)، وinclude يكتفي بتحذير — و*_once يتجنب إعادة التعريف.
- الرفع = مدخلات معادية : النوع الحقيقي مُتحقق، والحجم محدود، والملف مُعاد التسمية، والتخزين دون تنفيذ PHP — ملف PHP مرفوع وقابل للتنفيذ يسلم الخادم للمهاجم.
حالة مستمرة — رياد يرتب موقع الجمعية
موقع جمعية رياد يكبر : القائمة نفسها منسوخة في عشر صفحات، والاتصال بالقاعدة مُعاد نسخه في كل مكان — فكل تعديل يصبح عذابا. يرتب : config.php للإعدادات، وheader.php وfooter.php للتصميم، وfonctions.php للأدوات، وكل صفحة مُجمَّعة بـ require. ثم يضيف إرسال صور الفعاليات : الرفع يُعامَل كمدخل معادٍ — النوع الحقيقي مُتحقق، والملف مُعاد التسمية، ومخزن دون تنفيذ PHP. وفي 2.4، سيؤرخ هذه الصور بـ DateTime.
تتمة الخيط الرابط 2.2 : موقع رياد ينتقل من الترقيع المكرر إلى بنية نظيفة — ويستمر في 2.4.
1. التضمينات : اكتب مرة وأعد الاستعمال في كل مكان
الموقع الحقيقي يتشارك عناصر مشتركة (الترويسة، القائمة، تذييل الصفحة، الإعداد) : تكرارها في كل ملف مضنٍ ومستحيل الصيانة. PHP يقدم تعليمات التضمين (Inclusion) : include وrequire تُدخلان محتوى ملف في آخر. الفرق : require يسبب خَطأ قاتلا إن تعذر الملف — للملفات الضَرورية (الإعداد، الدوال الأساسية) ؛ وinclude يصدر تحذيرا بسيطا ويواصل — للملفات الاختيارية. وصيغتاهما require_once وinclude_once تضمنان تضمينا وَحيدا (لا إعادة تعريف) — وغالبا تُفضَّل. المعتاد : header.php وfooter.php مُضمَّنان في كل صفحة، وconfig.php مطلوب في أعلى السكربتات. رياد يعدل الآن قائمته في مكان واحد. ونقطة أَمان حاسمة : لا تُضمِّن أبدا مسارا جاء من مدخل مستخدم (include $_GET['page']) — فهي ثغرة تضمين ملف تعسفي.
2. التنظيم قبل أطر العمل
هذه التضمينات تؤسس تنظيم مشروع « يدويا » : فصل الكود في ملفات منطقية (الإعداد، الدوال، عناصر الواجهة، الصفحات) وتجميعها — خطوة أولى نحو بنية نظيفة، تفضي إلى MVC (القسم 4-1) والتحميل التلقائي (Autoloading) (القسم 3-3). المبادئ : افصِل حسب المسؤوليات، وأعِد الاستعمال بالتضمينات، وافصِل المنطق (المعالجة، الاستعلامات) عن العرض (HTML بعده)، ورتب في مجلدات واضحة (includes/ والصفحات وassets/ وuploads/ المؤمَّن)، وضع الملفات الحساسة (الإعداد بالمعرفات) خارِج جذر الويب. موقع رياد يعتمد هذه البنية : كل صفحة تبدأ بطلب الإعداد، وتعمل منطقها، ثم تُضمِّن العرض.
3. الملفات والرفع : اقرأ واكتب واحذر
PHP يَقرأ ويَكتب ملفات الخادم : file_get_contents() (قراءة الكل)، وfile_put_contents() (الكتابة)، وfopen()/fread()/fwrite()/fclose() (على مراحل، للملفات الكبيرة)، وfile_exists()، وunlink() (الحذف). الحالة الحساسة : الرفع (Uploads)، ملفات يرسلها المستخدم في $_FILES — تُعامَل كمدخلات معادية. الحمايات، كلها معا : تَحقَّق من النوع الحَقيقي (المحتوى، لا الامتداد المعلن القابل للتزييف) بقائمة بيضاء والحَجم ؛ وأعِد تَسمية الملف (لا اسم المستخدم أبدا) ؛ وخزنه خارِج جذر الويب أو في مجلد دون تنفيذ PHP — وإلا فملف PHP خبيث مرفوع ثم مُستدعى بالرابط يُنفَّذ ويُعرِّض الخادم للخطر ؛ وانقله بـ move_uploaded_file() بعد مراقبة رمز الخطأ. صور فعاليات رياد تتبع هذا البروتوكول تماما.
🔎 مثال ملموس — 🔎 مثال ملموس — صور فعاليات رياد، بأمان
كل الحمايات، كما لرفع رياد :
// التحقق من error والحجم والنوع الحقيقي (قائمة بيضاء)
$nom = bin2hex(random_bytes(8)) . '.jpg';
move_uploaded_file($_FILES['img']['tmp_name'],
__DIR__ . '/../uploads/' . $nom);
// مجلد بدون تنفيذ PHP
القراءة : مراقبة المحتوى، وإعادة تسمية عشوائية، وتخزين دون تنفيذ.
الدرس : لا تحتفظ أبدا بالاسم المقدم من المستخدم.
مفردات القسم
- include / require
- تُدخلان محتوى ملف في آخر ؛ وrequire يسبب خطأ قاتلا إن تعذر (الضروريات)، وinclude تحذيرا ويواصل (الاختياريات).
مثال بسيط: رياد يطلب config.php في أعلى كل صفحة.
ما ليس كذلك: نسخ ولصق القائمة نفسها في عشر صفحات.
رد فعل: الضروري = require.
- require_once / include_once
- تضمنان أن الملف لا يُضمَّن إلا مرة واحدة، متجنبتين التضمينات المتعددة وأخطاء إعادة التعريف — وغالبا تُفضَّل.
مثال بسيط: fonctions.php مطلوب بـ _once في كل صفحات رياد.
ما ليس كذلك: تضمين مكرر يعيد تعريف الدوال نفسها.
رد فعل: الملف المشترك = _once افتراضا.
- التنظيم بالتضمينات
- فصل الكود في ملفات منطقية (الإعداد، الدوال، الترويسة/التذييل، الصفحات) مُجمَّعة بالتضمينات ؛ خطوة أولى نحو بنية نظيفة (MVC، التحميل التلقائي).
مثال بسيط: موقع رياد : الإعداد والترويسة/التذييل والصفحات مُجمَّعة.
ما ليس كذلك: ملف ضخم يخلط المنطق والاستعلامات وHTML المكرر.
رد فعل: كود مكرر = ملف يُستخرَج ويُضمَّن.
- إدارة الملفات
- قراءة ملفات الخادم وكتابتها : file_get_contents وfile_put_contents وfopen/fread/fwrite وfile_exists وunlink.
مثال بسيط: رياد يقرأ قالبا ويكتب تصديرا بـ file_get_contents/put_contents.
ما ليس كذلك: رفع يُعامَل دون أي مراقبة.
رد فعل: ملف الخادم = تحقق من الوجود والحقوق.
- الرفع ($_FILES) — الأمان
- ملفات يرسلها المستخدم ($_FILES) : تحقق من النوع الحقيقي والحجم، وأعِد التَسمية، وخزن خارج الجذر أو دون تنفيذ PHP، وحدد الامتدادات.
مثال بسيط: كل صورة لرياد مُعادة التسمية ومخزنة دون تنفيذ PHP.
ما ليس كذلك: ملف محفوظ باسمه الأصلي في مجلد قابل للتنفيذ.
رد فعل: الرفع = مدخل معادٍ ببروتوكول كامل.
في التطبيق — تطبيقيا — تنظيم الكود وإدارة الملفات
- أنشئ header.php وfooter.php وضمِّنهما في صفحات عدة بـ require ؛ وأنشئ config.php مطلوبا في أعلى السكربتات.
- افهم الفرق require (قاتل) / include (تحذير) وفائدة require_once (تضمين وحيد).
- اقرأ ملفا واكتبه (file_get_contents / file_put_contents) ؛ وتحقق من وجوده (file_exists).
- عالج رفعا ($_FILES) بأَمان : تحقق من النوع الحقيقي والحجم، وأعِد تَسمية الملف، وخزنه في مجلد دون تنفيذ PHP — ولا تُضمِّن أبدا مسارا جاء من المستخدم.
نص جاهز — شرح الترتيب للمكتب الجمعوي (30 ثانية)
« رتبت الموقع : القائمة وتذييل الصفحة موجودان في نسخة واحدة، وكل صفحة تُضمِّنهما — فالتعديل يتم في مكان واحد. وللصور، كل ملف مُتحقق ومُعاد التسمية ومخزن في مجلد لا يمكن أن يُنفَّذ فيه أي سكربت : فحتى الملف الملفَّق يبقى غير مؤذٍ. »
يُقال مع عرض تعديل للقائمة ينعكس في كل مكان فورا.
قالب للنسخ — هيكل صفحة مُجمَّعة
موقع عرض صغير
خمس صفحات تتشارك الترويسة والتذييل : رياد يصحح القائمة مرة فيتبعها الموقع كله.
إعداد محمي
معرفات القاعدة خارج جذر الويب ومطلوبة في الأعلى : لا تُكشَف بالرابط أبدا ولا في المستودع.
تصدير البيانات
قائمة الأعضاء تُكتَب بـ file_put_contents بعد file_exists : قراءة وكتابة مراقبتان.
صور الفعاليات
رفع مُعاد التسمية والنوع الحقيقي مُتحقق ومجلد دون تنفيذ PHP : فيبقى المعرض غير مؤذٍ.
✓ ممارسات جيدة
- فصل الكود في ملفات منطقية وإعادة الاستعمال بالتضمينات.
- تفضيل require للملفات الضرورية و*_once ضد إعادة التعريف.
- معالجة الرفع بكل الحمايات (النوع الحقيقي، إعادة التسمية، دون تنفيذ).
✗ أخطاء شائعة
- تضمين مسار جاء من مدخل مستخدم (تضمين ملف تعسفي).
- الاحتفاظ باسم ملف مرفوع مقدم من المستخدم.
- تخزين الرفع في مجلد يُنفَّذ فيه PHP (سيطرة).
النقاط الأساسية
- التَضمينات (include/require) : إدخال ملف في آخر لتجنب التكرار (الترويسة، التذييل، الإعداد، الدوال). require = قاتل إن تعذر (الضروريات) ؛ وinclude = تحذير (الاختياريات) ؛ و*_once = تضمين وحيد.
- تنظيم الكود في ملفات منطقية مُجمَّعة بالتضمينات = خطوة أولى نحو بنية نظيفة (قبل MVC/التحميل التلقائي).
- ثَغرة يجب تجنبها : لا تُضمِّن أبدا مسارا جاء من مدخل مُستخدِم (include $_GET['page']) — تضمين ملف تعسفي.
- إدارة الملفات (file_get_contents/put_contents وfopen…) وخصوصا الرَفع ($_FILES) بأَمان : تحقق من النوع الحقيقي/الحجم، وأعِد التَسمية، وخزن دون تنفيذ PHP، وحدد الامتدادات (مصدر كلاسيكي لثغرات خطيرة).
تحدي 48 ساعة — طبق غدا
نظِّم مشروعا حقيقيا : استخرج الترويسة والتذييل والإعداد في ملفات مُضمَّنة بـ require/require_once، والمنطق قبل العرض. ثم أمِّن رفعا حقيقيا : النوع الحقيقي والحجم وإعادة التسمية ومجلد دون تنفيذ PHP.
- أستطيع شرح require مقابل include وفائدة *_once.
- أعرف هيكلة مشروع (الإعداد، الترويسة/التذييل، المنطق قبل العرض).
- أمَّنت رفعا حقيقيا بالبروتوكول الكامل.
أسئلة شائعة
كيف أنظم مشروع PHP « يدويا » بنظافة قبل استعمال إطار عمل ؟
استهدف الفَصل وإعادة الاستعمال، ضد « كود السباغيتي » (كل شيء مخلوط ومكرر دون بنية). (1) افصِل في ملفات منطقية : الإعداد (config.php)، والدوال القابلة لإعادة الاستعمال (أو الأصناف، المستوى 3)، والواجهة المشتركة (header.php وfooter.php)، والصفحات (المحتوى الخاص). (2) أعِد الاستعمال بالتضمينات : مكتوبة مرة ومُضمَّنة في كل مكان — تعديل في مكان واحد. (3) افصِل المنطق عن العرض : المنطق أولا (المعالجة، الاستعلامات) ثم HTML — الطريق نحو MVC (القسم 4-1). (4) هيكِل المجلدات : includes/ والصفحات وassets/ وuploads/ المؤمَّن. (5) أمِّن : الملفات الحساسة خارِج جذر الويب، ونقطة دخول وحيدة مثاليا، والأسرار خارج المستودع. هذا التنظيم يعلم المبادئ التي تُؤطِرها أُطُر العمل (MVC والتوجيه والتحميل التلقائي والإعداد والأمان).
لماذا رفع الملفات حساس جدا أمنيا، وكيف أديره بأمان ؟
الرفع يترك مستخدما يَضع ملفا على خادمك. السيناريو الأسوأ : ملف .php خبيث مرفوع ثم مُستدعى بالرابط — فيُنفِّذه الخادم ويستولي المهاجم على السيطرة (الملفات، القاعدة، كل شيء). مخاطر أخرى : ملفات ضخمة (منع الخدمة)، وأنواع مخادعة، والكتابة فوق الملفات. الحمايات، كلها معا : (1) لا تنفيذ أبدا — مجلد دون PHP أو خارِج جذر الويب : الحماية المفتاح. (2) إعادة التسمية (لا اسم المستخدم أبدا) باسم آمن وامتداد مراقب. (3) التحقق من النوع الحَقيقي (المحتوى، لا الامتداد المعلن) — قائمة بيضاء. (4) تحديد الحجم. (5) التحقق من الامتداد (قائمة بيضاء). (6) مراقبة رمز خطأ $_FILES والنقل بـ move_uploaded_file(). وفي مشروع حقيقي، فضل الأدوات المُجرَّبة في أطر العمل في موضوع بهذه الحساسية.
ما الحماية المفتاح للملفات المرفوعة ؟