Как переопределение URL влияет на параметр $_GET
для PHP?
Скажем, у меня есть URL-адрес, например http://example.com/index.php?p=contact
и я использую $_GET['p']
чтобы сообщить index.php
чтобы он служил на странице контактов. Если я использую правило перезаписи, которое преобразует URL-адрес в http://example.com/contact
, будет ли $_GET['p']
работать, как ожидалось?
Если да, не могли бы вы объяснить, почему это работает? Если нет, то какие стратегии могут быть использованы для решения проблемы, чтобы страница работала как с переписью, так и без нее?
Да, это будет работать так, как ожидалось.
Я бы поправил ответ Гранта на «Да, это будет работать в основном, как ожидалось».
В частности, поведение mod_rewrite
отношении существующих строк запросов может быть неожиданным. В качестве примера возьмем следующее правило, которое преобразует указанный вами URL-адрес:
RewriteRule /contact /index.php?p=contact
Это правильно перепишет /contact
с /index.php?p=contact
и имя страницы будет доступно через $_GET['p']
. Однако, если вы используете этот метод со сценарием, который использует параметры, отличные от названия страницы, он становится немного сложнее. Это правило также переводит /contact?person=Joe
to /index.php?p=contact
. Параметр person=Joe
полностью исчезает! Есть два способа справиться с этим.
Самый простой способ – использовать флаг [QSA]
(«строка запроса добавления») вашего правила, который поместит исходную строку запроса после параметров, заданных в правиле, переводя /contact?person=Joe
в /index.php?p=contact&person=Joe
:
RewriteRule /contact /index.php?p=contact [QSA]
Однако это позволяет перезаписать ваш параметр p=
. Посещение /contact?p=about
будет переписано в /index.php?p=contact&p=about
, поэтому $_GET['p']
вернет «about» в вашем скрипте, а не «contact». Чтобы решить эту проблему, вместо этого используйте переменную QUERY_STRING
:
RewriteRule /contact /index.php?%{QUERY_STRING}&p=contact
Это гарантирует, что $_GET['p']
всегда будет возвращать «контакт» при использовании этого правила, независимо от того, вовлекаются ли ваши посетители в ваши URL-адреса. 🙂
При переписывании URL это делается mod_rewrite – страница, полученная в конце, по-прежнему является «старой», то есть index.php? P = contact. Другими словами, браузер извлекает / связывается. mod_rewrite переписывает его на index.php? p = contact. Сценарий, из-за этого, не знает, что произошло какое-либо переписывание – его все еще называют его «обычным» способом. Поэтому такая переработка будет работать. Возможно, вам стоит подумать об этом как о переписывающем прокси-сервере, который запрашивает другую страницу, чем запрашиваемый исходный браузер.
Когда клиент запрашивает http://example.com/contact , сервер использует правило перезаписи, чтобы вместо этого использовать их http://example.com/index.php?p=contact . Клиент не сможет увидеть перезаписанный URL-адрес и даже не сможет сказать, что он был переписан. Запрос любого URL-адреса, поскольку клиент предоставит вам ту же страницу.
Не так ли, что изменение заголовков после отображения частей страницы может вызвать зависание на php-страницах? Как вы переписываете URL-адрес? Возможно, я неправильно понимаю …
Вы переписываете URL-адрес из /contact
/index.php?p=contact
, так что да, он будет работать так, как ожидалось.
В вашем случае это не сработает. mod_rewrite, после того, как он находит совпадение и переписывает http://example.com/index.php?p=contact к http://example.com/contact , выполняет внутреннюю переадресацию. Даже после перенаправления новый, перенаправленный URI все еще может быть сопоставлен с условием и далее перенаправлен.
В любом случае входящие URI не хранятся в памяти, поэтому даже Apache не может восстановить исходный URI. PHP, к тому моменту, когда он выполняется, также не знает оригинальный URI. Следовательно, вы теряете свои $ _GET-вары, поскольку переменные, отправленные через GET , содержатся в URL-адресе, который теперь преобразован, и PHP заполняет ассоциативный массив $ _GET, анализируя входящие запросы.
Предложение поддержки для обоих было бы кропотливым. Если у вас есть http://domain.com/segment1/segment2/segment3, вам нужно связать сегменты с чем-то значимым. Вы разделили бы свой домен и взорвались бы на «/», и в вашем случае вы могли бы сказать, что первый сегмент запрашивает страницу, а с http://example.com/contact/ вы можете извлечь страницу = «контакт»,