$ _GET и переписывание URL для PHP

Как переопределение 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/ вы можете извлечь страницу = «контакт»,