الحصول على URL الكامل في PHP: لا تخترع العجلة ولا تفقد الأداء
\n\nكل مطور PHP يواجه عاجلاً أم آجلاً سؤالاً: "كيف أحصل على الرابط الكامل للصفحة الحالية؟". قد يبدو الأمر بسيطاً – استخدم $_SERVER['REQUEST_URI'] وأضف النطاق، وانتهى الأمر. لكن الشيطان يكمن في التفاصيل. سؤال "الحصول على URL الكامل في PHP" على Stack Overflow حصد آلاف المشاهدات وعشرات الإجابات. وهذا ليس من فراغ.
في هذا المقال، سنشرح كيف تحصل على URL الكامل في PHP بطريقة صحيحة وسريعة وخالية من الأخطاء. ستتعلم الفرق بين HTTP_HOST و SERVER_NAME، وكيفية تحديد البروتوكول (HTTPS أو HTTP) بشكل صحيح، ولماذا لا يجب نسخ الكود من الإنترنت بشكل أعمى. هيا بنا!
لماذا الطريقة البسيطة ليست دائماً الأفضل؟
\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
في العالم الحقيقي، هذه الشروط لا تتحقق دائماً. إذا كان الموقع يعمل عبر HTTPS، ستحصل على رابط يبدأ بـ http:// مما يسبب خطأ المحتوى المختلط في المتصفح. إذا كان المنفذ غير قياسي (مثل 8080)، سيتم فقدانه. وإذا قام مخترق بتزوير رأس Host، قد تحصل على رابط لنطاق آخر.
\n\nمكونات URL الكامل: تحليل شامل
\n\nقبل كتابة حل شامل، دعنا نتذكر مما يتكون الرابط الكامل:
\n\nscheme://host:port/path?query#fragment\n\nفي PHP، لدينا العناصر التالية من المصفوفة الشاملة $_SERVER:
- \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
الحل الصحيح: دالة 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