الحصول على URL الكامل في PHP: دليل سريع وخالي من الأخطاء

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

الحصول على URL الكامل في PHP: لا تخترع العجلة ولا تفقد الأداء

\n\n

كل مطور PHP يواجه عاجلاً أم آجلاً سؤالاً: "كيف أحصل على الرابط الكامل للصفحة الحالية؟". قد يبدو الأمر بسيطاً – استخدم $_SERVER['REQUEST_URI'] وأضف النطاق، وانتهى الأمر. لكن الشيطان يكمن في التفاصيل. سؤال "الحصول على URL الكامل في PHP" على Stack Overflow حصد آلاف المشاهدات وعشرات الإجابات. وهذا ليس من فراغ.

\n\n

في هذا المقال، سنشرح كيف تحصل على URL الكامل في PHP بطريقة صحيحة وسريعة وخالية من الأخطاء. ستتعلم الفرق بين HTTP_HOST و SERVER_NAME، وكيفية تحديد البروتوكول (HTTPS أو HTTP) بشكل صحيح، ولماذا لا يجب نسخ الكود من الإنترنت بشكل أعمى. هيا بنا!

\n\n

لماذا الطريقة البسيطة ليست دائماً الأفضل؟

\n\n

الطريقة الأكثر وضوحاً تبدو كالتالي:

\n\n
<?php\n$fullUrl = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];\n?>
\n\n

هذا الكود يعمل، ولكن فقط إذا كان لديك:

\n
    \n
  • بروتوكول HTTP فقط (وليس HTTPS)
  • \n
  • لا يوجد منفذ غير 80 أو 443
  • \n
  • الخادم يرسل رأس Host بشكل صحيح
  • \n
\n\n

في العالم الحقيقي، هذه الشروط لا تتحقق دائماً. إذا كان الموقع يعمل عبر HTTPS، ستحصل على رابط يبدأ بـ http:// مما يسبب خطأ المحتوى المختلط في المتصفح. إذا كان المنفذ غير قياسي (مثل 8080)، سيتم فقدانه. وإذا قام مخترق بتزوير رأس Host، قد تحصل على رابط لنطاق آخر.

\n\n

مكونات URL الكامل: تحليل شامل

\n\n

قبل كتابة حل شامل، دعنا نتذكر مما يتكون الرابط الكامل:

\n\n
scheme://host:port/path?query#fragment
\n\n

في PHP، لدينا العناصر التالية من المصفوفة الشاملة $_SERVER:

\n
    \n
  • scheme – البروتوكول (HTTP أو HTTPS). لا يوجد مفتاح مباشر، لكن يمكن تحديده عبر $_SERVER['HTTPS'] أو $_SERVER['REQUEST_SCHEME'] (متاح من PHP 7.4).
  • \n
  • host – النطاق. هناك مرشحان: HTTP_HOST (من رأس Host) و SERVER_NAME (من إعدادات الخادم).
  • \n
  • port – المنفذ. $_SERVER['SERVER_PORT']. إذا كان المنفذ قياسياً (80 لـ HTTP، 443 لـ HTTPS)، يمكن حذفه.
  • \n
  • path – المسار. $_SERVER['REQUEST_URI'] يحتوي على المسار وسلسلة الاستعلام.
  • \n
  • query – سلسلة الاستعلام. يمكن الحصول عليها بشكل منفصل عبر $_SERVER['QUERY_STRING'].
  • \n
  • fragment – المرساة (العلامة #). لا يتم إرسالها إلى الخادم، لذا لا يمكن الحصول عليها.
  • \n
\n\n

الحل الصحيح: دالة getFullUrl()

\n\n

إليك طريقة موثوقة وفعالة للحصول على URL الكامل في PHP:

\n\n
<?php\nfunction getFullUrl(): string {\n    // تحديد البروتوكول\n    $scheme = 'http';\n    if (\n        (isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] === 'on' || $_SERVER['HTTPS'] === '1'))\n        || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https')\n    ) {\n        $scheme = 'https';\n    }\n\n    // المضيف: نفضل HTTP_HOST ولكن نتحقق من عدم الفراغ\n    $host = $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'] ?? 'localhost';\n\n    // المنفذ: نضيفه فقط إذا كان غير قياسي\n    $port = (int) ($_SERVER['SERVER_PORT'] ?? 80);\n    $portStr = '';\n    if (\n        ($scheme === 'http' && $port !== 80) ||\n        ($scheme === 'https' && $port !== 443)\n    ) {\n        $portStr = ':' . $port;\n    }\n\n    // URI\n    $uri = $_SERVER['REQUEST_URI'] ?? '/';\n\n    return $scheme . '://' . $host . $portStr . $uri;\n}\n?>
\n\n

هذه الدالة تراعي:

\n
    \n
  • بروتوكول HTTPS (بما في ذلك عبر الخوادم الوسيطة مع رأس X-Forwarded-Proto).
  • \n
  • المنافذ غير القياسية.
  • \n

المدونات

توصيات الكتب