$ _GET и перезапись URL для PHP - PullRequest
10 голосов
/ 03 февраля 2009

Как перезапись URL влияет на параметр $_GET для PHP?

Скажем, у меня есть URL-адрес, такой как http://example.com/index.php?p=contact, и я использую $_GET['p'], чтобы сообщить index.php, чтобы обслуживать страницу контактов. Если я использую правило перезаписи, которое преобразует URL-адрес в http://example.com/contact, будет ли $_GET['p'] работать как положено?

Если да, не могли бы вы пояснить, почему это работает? Если нет, какие стратегии можно использовать для решения проблемы, чтобы страница работала как с перезаписью, так и без нее?

Ответы [ 7 ]

32 голосов
/ 03 февраля 2009

Я бы изменил ответ Гранта на «Да, это будет работать в основном , как и ожидалось».

В частности, поведение mod_rewrite в отношении существующих строк запросов может быть удивительным. В качестве примера, давайте возьмем следующее правило, которое преобразует указанный вами URL:

RewriteRule /contact /index.php?p=contact

Это правильно перезапишет /contact в /index.php?p=contact, и имя страницы будет доступно через $_GET['p']. Однако, если вы используете эту технику со скриптом, который использует параметры, отличные от имени страницы, он становится немного хитрее. Это правило также переводит /contact?person=Joe в /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-адреса. : -)

4 голосов
/ 03 февраля 2009

Да, это будет работать, как ожидалось.

1 голос
/ 03 февраля 2009

Когда клиент запрашивает http://example.com/contact,, сервер использует правило перезаписи, чтобы вместо них обслуживать http://example.com/index.php?p=contact. Клиент не сможет увидеть переписанный URL-адрес и даже не сможет сказать, что он был переписан. Запрос любого URL-адреса в качестве клиента даст вам ту же самую страницу.

1 голос
/ 03 февраля 2009

При перезаписи URL это делается mod_rewrite - страница, полученная в конце, все еще является «старой», то есть index.php? P = contact. Другими словами, браузер получает / контакт. Затем mod_rewrite переписывает его в index.php? p = contact. Из-за этого сценарий не знает, что произошло какое-либо переписывание - его все еще называют «обычным» способом. Поэтому такая перезапись будет работать. Возможно, вы захотите думать о нем как о переписывающем прокси, который запрашивает страницу, отличную от той, которую запрашивал исходный браузер.

0 голосов
/ 03 февраля 2009

В вашем случае это не сработает. 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/ вы можете извлечь страницу = 'contact'

0 голосов
/ 03 февраля 2009

Не правда ли, что изменение заголовков после рендеринга частей страницы может привести к сбоям на php-страницах? Как вы переписываете URL? Может быть, я неправильно понимаю ...

0 голосов
/ 03 февраля 2009

Вы переписываете URL с /contact на /index.php?p=contact, так что да, он будет работать как положено.

...