طَبِّقْهاتعلّم المبدأ، وطبّقه بيدكمقرر 132 · تقنيات تطوير الواجهات الخلفية
الدرس 9 · الوحدة 4: إنشاء وحدات من الجانب الخادم لوظائف التطبيق

تقسيم التطبيق إلى ملفات: include و require

اكتب كل جزء مرة واحدة، وابنِ الصفحات من وحدات. ⏱ نحو 30 دقيقة.

بعد هذا الدرس ستستطيع أن:
  • تشرح فائدة تقسيم التطبيق إلى وحدات.
  • تميّز include و require و require_once وتختار المناسب.
  • تبني الصفحات من ترويسة وتذييل ودوال مشتركة.
  • تستخدم __DIR__ للمسارات، وتنظّم المشروع في مجلدات.

١مشكلة النسخ واللصق

موقع فيه عشر صفحات، وكل صفحة تكرر الترويسة والقائمة والتذييل ودوال مثل e() و price(). الآن طُلب منك إضافة رابط جديد للقائمة: ستعدّل عشرة ملفات، وستنسى واحدًا حتمًا.

الحل: ضع كل جزء مشترك في ملف واحد، ثم ضمّنه حيث تحتاجه. هكذا يصير التطبيق وحدات Modules صغيرة، لكل وحدة مهمة واحدة.

٢include و require

كلاهما يضع محتوى ملف آخر في مكانه ويشغّله، كأنك نسخته هناك. والفرق عند غياب الملف:

الأمرإن لم يوجد الملف
require 'x.php';خطأ قاتل: يتوقف التطبيق. استخدمه للملفات الضرورية (الدوال، والإعداد، والاتصال بقاعدة البيانات).
include 'x.php';تحذير ويكمل التنفيذ. للأجزاء الاختيارية فقط، مثل شريط إعلانات.
require_once 'x.php';مثل require، لكن لا يضمّن الملف مرتين. مهم لملفات الدوال والأصناف (تعريف دالة مرتين خطأ).
✗ خطأ
<?phprequire 'helpers.php';echo "لن تصل إلى هنا";
✓ صواب
<?phpinclude 'banner.php';echo "وصلنا رغم غياب الملف";

كلا الملفين غير موجود. require أوقفت التطبيق بخطأ قاتل، و include اكتفت بتحذير وأكملت. وفي الحالتين: الأصل ألا يغيب ملف تحتاجه!

٣موقع من وحدات

هذا موقع صغير بأسلوب احترافي. الصفحات index.php و products.php قصيرة: تضمّن الدوال، وتحدد العنوان، وتضمّن الترويسة، ثم تكتب محتواها الخاص فقط، ثم تضمّن التذييل. تنقّل بين تبويبات الملفات:

<?phprequire __DIR__ . '/inc/functions.php';$title = 'الرئيسية';require __DIR__ . '/inc/header.php';?><p>أهلًا بك في متجر الواحة. لدينا <?= count(products()) ?> منتجات.</p><?php require __DIR__ . '/inc/footer.php'; ?>

الصفحتان تشتركان في الترويسة والتذييل والدوال. لإضافة رابط إلى القائمة تعدّل ملفًّا واحدًا: inc/header.php. ولاحظ أن المتغير $title الذي عرّفته الصفحة ظهر داخل header.php: الملف المضمَّن يرى متغيرات الملف الذي ضمّنه.

🧪 مختبر الخادمأضف رابطًا ثالثًا «من نحن» في inc/header.php، ثم تنقّل بين الصفحتين: ظهر في كلتيهما.

٤المسارات: استخدم __DIR__

المسار النسبي مثل 'inc/header.php' يُحسب من المجلد الذي يعمل منه PHP، لا من مكان الملف الذي كتبته فيه. فإن ضمّن ملف داخل مجلد ملفًّا آخر، قد يضيع المسار. الحل الآمن: الثابت __DIR__، وهو مجلد الملف الحالي دائمًا:

<?php// داخل admin/users.phprequire __DIR__ . '/../inc/functions.php';   // ‎..‎ تعني المجلد الأعلىrequire __DIR__ . '/../config.php';

٥بنية مشروع مرتّبة

مع نمو التطبيق نفصل الملفات حسب دورها. هذه بنية بسيطة ستستخدمها في مشروع المقرر:

my-app/├── public/             ← جذر الموقع (DocumentRoot): ما يُطلب من المتصفح فقط│   ├── index.php│   ├── products.php│   └── css/style.css├── inc/                ← الوحدات: لا تُطلب مباشرة│   ├── config.php      ← الإعدادات وكلمات المرور│   ├── db.php          ← الاتصال بقاعدة البيانات│   └── functions.php└── templates/          ← قوالب العرض    ├── header.php    └── footer.php

توقّع وتحقّق

ملف الاتصال بقاعدة البيانات ضروري. نضمّنه بـ:

ضروري ولا نريده مرتين.

ماذا تفعل include عند غياب الملف؟

بخلاف require.

__DIR__ تعني:

ثابت سحري في PHP.

هل يرى الملف المضمَّن متغيرات الملف الذي ضمّنه؟

كأن الكود نُسخ في مكانه.

الخلاصة

تحدٍّ برمجي: أزل التكرار

متوسط

الصفحتان index.php و courses.php تكرران الدالة e() والقائمة والتذييل. انقل الأجزاء المشتركة إلى ملفي layout، ثم أضف رابطًا ثالثًا للقائمة.

المطلوب:
  • انقل الدالة e() والقائمة <nav> إلى layout/top.php، والتذييل إلى layout/bottom.php.
  • في كل صفحة: require للملفين (مع __DIR__)، ويبقى فيها محتواها الخاص فقط.
  • أضف إلى القائمة رابطًا ثالثًا: <a href="contact.php">تواصل</a> (مرة واحدة في top.php).
👀 اعرض الاستجابة المطلوبة
✓ التحقق الآلي: يرسل المختبر هذه الطلبات إلى خادمك بالترتيب ثم يفحص الاستجابات
  1. GET /index.php
  2. GET /courses.php
  • الكود يعمل بلا أخطاء أو تحذيرات
  • الرئيسية: فيها القائمة الجديدة والعنوان والتذييل
  • الدورات: فيها القائمة الجديدة والمحتوى والتذييل
  • الصفحتان تضمّنان layout/top.php و layout/bottom.php
  • القائمة لا تتكرر داخل الصفحة
  • الدالة e() معرّفة مرة واحدة فقط (في top.php)

💡 تلميح 1
ابدأ بنسخ السطور المشتركة إلى top.php، ثم احذفها من الصفحتين، وضع مكانها <?php require __DIR__ . '/layout/top.php'; ?>
💡 تلميح 2
إن رأيت «Cannot redeclare e()» فالدالة ما زالت في إحدى الصفحتين.

حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.

<?php require __DIR__ . '/layout/top.php'; ?><h1>معهد التدريب</h1><p>مرحبًا بك.</p><?php require __DIR__ . '/layout/bottom.php'; ?>
انتقل إلى تقييم الدرساختيار من متعدد، وصح وخطأ، وأكمل الفراغ، وتتبّع الناتج.ابدأ التقييم ←

📝 معلم؟ أرسل ملاحظة للمؤلف عن هذا الدرس