طَبِّقْهاتعلّم المبدأ، وطبّقه بيدكمقرر 132 · تقنيات تطوير الواجهات الخلفية
الدرس 24 · الوحدة 11: اختيار بيئة الاستضافة وتكوين الخادم

خيارات الاستضافة وتكوين الخادم

الخطوة الأولى في النشر: اختر البيئة وجهّزها. ⏱ نحو 30 دقيقة.

بعد هذا الدرس ستستطيع أن:
  • تقارن الاستضافة المشتركة و VPS والسحابية وتختار المناسبة.
  • تحدد معايير اختيار بيئة الاستضافة لتطبيق PHP.
  • تضبط إعدادات PHP للإنتاج، وتفحص جاهزية الخادم بصفحة مخصصة.
  • تفصل إعدادات التطوير عن الإنتاج بمتغيرات البيئة أو ملف إعداد خاص.

١من جهازك إلى الإنترنت

تطبيقك يعمل على localhost، أي على جهازك وحدك. لينفتح للناس يحتاج خادمًا متصلًا بالإنترنت طوال الوقت، بعنوان ثابت، وفيه Apache و PHP وقاعدة بيانات. ونادرًا ما تملك جهازًا كهذا، فتستأجره من شركة استضافة. والوحدات الأربع الأخيرة في المقرر هي رحلة النشر: اختيار البيئة ← النشر ← النطاق ← الاختبار.

٢أنواع الاستضافة

النوعالفكرةتتحكم فيمناسب لـ
مشتركة Sharedخادم واحد يتشاركه مئات المواقع، ولوحة تحكم جاهزة (cPanel أو مثلها) فيها PHP و MySQL.ملفاتك وقاعدتك وبعض إعدادات PHP فقطالمواقع الصغيرة، والمشاريع الطلابية، وأول نشر
خادم افتراضي خاص VPSجزء محجوز من خادم كبير يعمل كأنه جهاز مستقل، بنظام Linux تديره أنت.كل شيء: النظام وApache وPHP والجدار الناريالتطبيقات المتوسطة، ومن يحتاج إعدادات خاصة
منصات سحابية Cloud / PaaSترفع الكود (أو حاوية Docker) والمنصة تشغّله وتوسّعه تلقائيًّا حسب الضغط.الكود والإعدادات، والمنصة تدير الخوادمالتطبيقات الكبيرة والمتغيرة الضغط
مشتركةVPSسحابية
سهولة البدءالأسهلتحتاج خبرة Linuxمتوسطة
التحكممحدودكاملواسع عبر إعدادات المنصة
مسؤولية الأمان والتحديثاتعلى الشركة غالبًاعليك أنتمشتركة
التكلفةالأقل (وفيها مجاني)متوسطةحسب الاستخدام

لمشروع المقرر تكفي استضافة مشتركة. مثال مجاني للتدريب: InfinityFree؛ تذكر صفحته الرسمية (في وقت كتابة الدرس) أنها تقدم PHP 8.4 وقواعد MySQL/MariaDB ونطاقًا فرعيًّا مجانيًّا وشهادة SSL مجانية ورفعًا بـ FTP أو مدير الملفات ودعمًا لـ .htaccess، بلا بطاقة ائتمان، مع شرط حد أدنى من الزيارات شهريًّا ليبقى الموقع فعالًا. العروض المجانية تتغير، فراجع شروطها الحالية قبل الاعتماد عليها، ولا تضع عليها بيانات حقيقية حساسة.

٣كيف تختار؟

  1. متطلبات التطبيق: إصدار PHP (8.1 فأحدث لمشروعنا)، والإضافات (pdo_mysql و mbstring)، وقاعدة البيانات.
  2. الحجم والضغط المتوقع: كم زائرًا في اليوم؟ كم حجم الملفات والقاعدة؟
  3. مكان الخادم: الأقرب لمستخدميك أسرع. وبعض البيانات (الحكومية والصحية) تشترط الأنظمة السعودية حفظها داخل المملكة.
  4. الدعم والنسخ الاحتياطي: هل تأخذ الشركة نسخًا احتياطية؟ هل يوجد دعم فني؟
  5. HTTPS والنطاق: شهادة SSL مجانية؟ هل تربط نطاقك الخاص؟

٤تكوين PHP للإنتاج

إعدادات XAMPP مصممة للتطوير: تعرض الأخطاء وتسمح بكل شيء. على الخادم الحقيقي نغيّر إعدادات php.ini (أو من لوحة التحكم، أو بـ ini_set في أول التطبيق):

الإعدادالتطويرالإنتاجلماذا؟
display_errorsOnOffلا تكشف المسارات والتفاصيل للزوار.
log_errorsOnOnالأخطاء تُسجَّل في ملف للمطوّر.
date.timezone—Asia/Riyadhالتواريخ والأوقات بتوقيت المملكة.
upload_max_filesize40Mحسب الحاجة (مثلًا 5M)حد حجم الملف المرفوع.
session.cookie_secureOffOnكوكي الجلسة عبر HTTPS فقط.
expose_phpOnOffلا تعلن إصدار PHP في الترويسة X-Powered-By.

و phpinfo() تعرض كل الإعدادات والإضافات المفعّلة؛ مفيدة للتحقق، لكن احذف صفحتها فورًا بعد الاستخدام لأنها تكشف الكثير. والأفضل صفحة فحص مخصصة لا تكشف إلا ما يلزم:

<?php// health.php: فحص جاهزية الخادم قبل النشر وبعدهheader('Content-Type: application/json; charset=utf-8'); $checks = [    'php_8_1_or_newer' => version_compare(PHP_VERSION, '8.1', '>='),    'pdo'              => extension_loaded('pdo'),    'mbstring'         => extension_loaded('mbstring'),    'json'             => extension_loaded('json'),    'display_errors_off' => !ini_get('display_errors'),    'timezone_riyadh'  => date_default_timezone_get() === 'Asia/Riyadh',];$ok = !in_array(false, $checks, true);http_response_code($ok ? 200 : 500);echo json_encode(['ok' => $ok, 'php' => PHP_VERSION, 'checks' => $checks], JSON_PRETTY_PRINT);

في المختبر display_errors مفعّل لأنه بيئة تعلّم، فيفشل فحصه ويرد الفحص بـ 500. وهذا بالضبط ما نريد أن تكشفه الصفحة قبل نشر حقيقي.

٥الإعدادات حسب البيئة

التطبيق نفسه يعمل في بيئتين: التطوير على جهازك، والإنتاج على الخادم. بيانات الاتصال بالقاعدة مختلفة، وعرض الأخطاء مختلف. لا نعدّل الكود عند كل نشر؛ بل نقرأ البيئة من متغير، ونختار الإعدادات:

<?php// config.php$env = getenv('APP_ENV') ?: 'development'; $config = [    'development' => [        'db_dsn'  => 'mysql:host=localhost;dbname=app;charset=utf8mb4',        'db_user' => 'root', 'db_pass' => '',        'debug'   => true,    ],    'production' => [        'db_dsn'  => getenv('DB_DSN'),            // من لوحة الاستضافة، لا من الكود        'db_user' => getenv('DB_USER'), 'db_pass' => getenv('DB_PASS'),        'debug'   => false,    ],][$env]; ini_set('display_errors', $config['debug'] ? '1' : '0');date_default_timezone_set('Asia/Riyadh');return $config;

توقّع وتحقّق

موقع طلابي صغير لأول نشر. الأنسب غالبًا:

أسهل وأرخص.

في VPS، من مسؤول عن تحديثات النظام والأمان؟

تحكم كامل = مسؤولية كاملة.

display_errors على الخادم الحقيقي:

مع log_errors On.

صفحة phpinfo() بعد التحقق من الإعدادات:

تكشف معلومات حساسة.

الخلاصة

تحدٍّ برمجي: صفحة جاهزية الخادم

متوسط

قبل رفع التطبيق، نريد صفحة ready.php تفحص الخادم الجديد وترد JSON.

المطلوب:
  • الفحوص: php (الإصدار 8.1 فأحدث)، و extensions (الإضافات pdo و mbstring و json و session كلها مفعّلة)، و uploads_writable (مجلد uploads موجود أو تنشئه، وقابل للكتابة).
  • الرد: {"ok":true,"checks":{"php":true,"extensions":true,"uploads_writable":true},"missing":[]} و missing قائمة الإضافات الناقصة.
  • الرمز 200 إن نجح الكل، وإلا 503 Service Unavailable.
👀 اعرض الاستجابة المطلوبة
✓ التحقق الآلي: يرسل المختبر هذه الطلبات إلى خادمك بالترتيب ثم يفحص الاستجابات
  1. GET /ready.php
  • الكود يعمل بلا أخطاء أو تحذيرات
  • الرد JSON بالشكل المطلوب تمامًا
  • الكل ناجح ← 200
  • تستخدم version_compare و extension_loaded و is_writable

💡 تلميح 1
version_compare(PHP_VERSION, '8.1', '>=')
💡 تلميح 2
الإضافات الناقصة: array_values(array_filter($required, fn($e) => !extension_loaded($e)))

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

<?phpheader('Content-Type: application/json; charset=utf-8'); $required = ['pdo', 'mbstring', 'json', 'session'];$missing = array_values(array_filter($required, fn($e) => !extension_loaded($e))); $dir = __DIR__ . '/uploads';if (!is_dir($dir)) {    mkdir($dir, 0755, true);}$checks = [    'php' => version_compare(PHP_VERSION, '8.1', '>='),    'extensions' => count($missing) === 0,    'uploads_writable' => is_writable($dir),];$ok = !in_array(false, $checks, true);http_response_code($ok ? 200 : 503);echo json_encode(['ok' => $ok, 'checks' => $checks, 'missing' => $missing]);
انتقل إلى تقييم الدرساختيار من متعدد، وصح وخطأ، وأكمل الفراغ، وتتبّع الناتج.ابدأ التقييم ←

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