Помимо первого правила, перекрывающего второе, ваше второе правило также не будет работать, потому что вы пытаетесь сопоставить строку запроса в RewriteRule. Попробуйте что-то вроде этого:
RewriteEngine On
RewriteBase /
RewriteCond %{QUERY_STRING} ^name=([^/.&]+)/?$
RewriteCond %{ENV:REDIRECT_LOOP} !1
RewriteRule ^page\.php$ /%1? [NS,R=301,L]
RewriteRule ^([^/.]+)/?$ page.php?name=$1 [NS,QSA,E=LOOP:1]
(я включил флаг QSA
, чтобы URL типа /foobar?foo=bar
был переписан на /page.php?name=foobar&foo=bar
вместо просто /page.php?name=foobar
. Если вы этого не хотите, оставьте его .)
Примечание: Второе RewriteCond
предназначено для предотвращения повторного сопоставления первого правила после сопоставления второго. Проблема заключается в том, что в контексте .htaccess mod_rewrite действует более или менее так, как если бы все правила имели флаг PT
, вызывая повторный запуск набора правил с начала после каждой перезаписи. даже внутренние. Или , чтобы процитировать документацию :
"Если вы используете RewriteRule в файлах .htaccess или в разделах , важно иметь некоторое представление о том, как обрабатываются правила. Упрощенная форма этого состоит в том, что после обработки правил переписанный запрос передается механизму синтаксического анализа URL, чтобы сделать с ним все возможное. Возможно, что при обработке переписанного запроса файл .htaccess или раздел могут быть обнаружены снова, и, таким образом, может быть запущен набор правил. снова с самого начала. Чаще всего это происходит, если одно из правил вызывает перенаправление - либо внутреннее, либо внешнее - и процесс запроса запускается заново. "
Обходной путь, который я использую, - установить пользовательскую переменную среды с E=LOOP:1
, когда внутренняя перезапись срабатывает, и проверить ее перед выполнением внешней перезаписи. Обратите внимание, что, когда обработка запроса возобновляется после внутренней перезаписи, Apache добавляет REDIRECT_
к именам всех переменных среды, установленных во время предыдущего прохода, поэтому даже если переменная, которую мы установили, называется просто LOOP
, нам нужно чек на это REDIRECT_LOOP
.