Документация
ЧПУ без .htaccess
ЧПУ — это урлы понятные человеку.
То есть не бессмысленный набор символов вида
http://domain.ru/modules.php?module=vitrina&action=superstition&cat_id=999&product_id=7293
,
а читаемый http://domain.ru/vitrina/snowboards/burton_genie
.
Ну, это лирика :)
Достичь ЧПУ можно с помощью так называемых преобразований строки урла в ту же «бессмысленную» с человеческой точки зрения строку, а можно заранее предусмотреть ЧПУ в разработки скриптов. Как бы то ни было, без преобразований урла не обойтись.
Как уже знаем, в nginx не существует апачевского .htaccess, где можно было бы настроить правила для столь популярного mod_rewrite, собственно mod_rewrite — это модуль именно для Apache...
Но не стоит расстраиваться! У nginx есть свой модуль — ngx_http_rewrite_module. По моему скромному мнению, модуль rewrite у nginx более гибок, понятен и прост в освоении, нежели mod_rewrite у Apache. Хотя, оба требуют особого понимания работы системы «ревратов» для написания правил :)
Правила преобразования нужно прописывать в конфигурационный файл сайта.
Пример правила перезаписывания урла
rewrite ^/users/(.*)$ /show.php?user=$1 last;
Если серверу приходит запрос /users/alex, то мы такой запрос перепишем на другой /show.php?user=alex и выполнится скрипт /show.php с GET-параметром user. При этом пользователь будет видеть в строке адреса в браузере первоначальный запрос.
Приведенный пример лишь показывает как можно преобразовать строку запроса. Опять же по моему скромному мнению, так делать нельзя. Нужно сводить все запросы на несуществующие файлы к единому обработчику-роутеру (это может быть index.php), который разберет урл запроса и передаст управление нужным контроллерам с нужными данными.
Примерно это должно выглядеть так:
server {
listen 80;
server_name my-domain.local www.my-domain.local;
index index.html index.php;
root home/my-domain.local/public_html;
location / {
try_files $uri $uri/index.html $uri/index.php @router;
}
location @router {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
include fastcgi_params;
}
location ~ \.php$ {
try_files $uri @router;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
Основное правило перезаписей — чем меньше условий и правил, тем лучше :)
Пример типичных правил для Drupal
В Apache мы имеем следующее:
<FilesMatch "\.(engine|inc|info|install|make|module|profile|test|po|sh|.*sql|theme|tpl(\.php)?|xtmpl)$|^(\..*|Entries.*|Repository|Root|Tag|Template)$">
Order allow,deny
</FilesMatch>
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteRule ^ index.php [L]
Перепишем правило для nginx:
location ~* \.(engine|inc|info|install|make|module|profile|test|po|sh|.*sql|theme|tpl(\.php)?|xtmpl)$ {
deny all;
}
location ~* ^/(\..*|Entries.*|Repository|Root|Tag|Template)$ {
deny all;
}
location /favicon.ico {
}
location / {
try_files $uri @drupal;
## либо так:
#try_files $uri /index.php$is_args$args;
## другой вариант:
#if (!-f $request_filename) {
# rewrite ^(.*)$ /index.php;
#}
}
location @drupal {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
include fastcgi_params;
}
Примечание. В примере излишне длинная строка запретных запросов, которую можно было бы избежать, убрав из «видимой» части нежелательные файлы и папки. Данное поведение неправильно, но для примера осталось неизменным.
Пример типичных правил для Joomla
RewriteBase /
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteCond %{REQUEST_URI} !^/index\.php
RewriteCond %{REQUEST_URI} /component/|(/[^.]*|\.(php|html?|feed|pdf|vcf|raw))$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php [L]
Перепишем правило для nginx:
location / {
try_files $uri @joomla;
}
location @joomla {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
include fastcgi_params;
}
Примечание. В примере излишние условия проверок убраны при переводе на nginx (их можно было убрать и в Apache).
Пример типичных правил для Wordpress
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
Перепишем правило для nginx:
location / {
try_files $uri @wordpress;
}
location @wordpress {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
include fastcgi_params;
}
Пример типичных правил для MODX
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_USER_AGENT} ^.*internal\ dummy\ connection.*$ [NC]
RewriteRule .* - [F,L]
RewriteRule ^(manager|assets) - [L]
# For Friendly URLs
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
Перепишем правило для nginx:
if ($http_user_agent ~* "internal dummy connection") {
return 403;
}
location /manager {
}
location /assets {
}
location / {
try_files $uri @modx;
## или так:
#try_files $uri /index.php?q=$uri&$args;
## другой вариант:
#if (!-f $request_filename) {
# rewrite ^(.*)$ /index.php?q=$1;
#}
}
location @modx {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
include fastcgi_params;
fastcgi_param QUERY_STRING q=$uri&$args;
}
Как видим, здесь немного есть отличия, скрипт index.php не может (не хочет?) сам определить запрошенный урл и желает его получить в GET-переменную q. Что ж, мило :)
Кроме того, можно смело избавиться от первой строчки, где проверяется наличие строки "internal dummy connection" в юзер-агенте, потому что это фикс для Apache, а у нас-то с вами nginx, не так ли? :)
Пример типичных правил для Битрикс
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !/bitrix/urlrewrite.php$
RewriteRule ^(.*)$ /bitrix/urlrewrite.php [L]
Перепишем правило для nginx:
location / {
try_files $uri @bitrix;
}
location @bitrix {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root/bitrix/urlrewrite.php;
include fastcgi_params;
}
Без комментариев ;)