.htaccess для CMS и фреймворков

Типовой .htaccess для популярных PHP-CMS и фреймворков: Laravel, Symfony, Joomla, Drupal, 1С-Битрикс, Yii2, OpenCart, CodeIgniter, OctoberCMS — что в нём, какие правки нужны и какие ошибки встречаются чаще всего. WordPress вынесен в отдельный хаб «.htaccess для WordPress». Если уже что-то пошло не так — гид «Почему .htaccess не работает»; проверить синтаксис файла — линтер; аудит безопасности — аудит .htaccess. Готовые блоки под типовые задачи — в рецептах .htaccess.

Почти у всех современных фреймворков один паттерн: все запросы к несуществующим файлам и каталогам → index.php/public/index.php (фронт-контроллер). Разделы ниже покажут, как именно это делается в каждом фреймворке, какие бывают отличия и что чаще всего приходится дополнительно настраивать. Блокировки по IP, Basic-auth, заголовки безопасности — в гидах «Безопасность» и «Ошибки».

1. Общий паттерн: фронт-контроллер

Почти все современные PHP-фреймворки используют один архитектурный приём: единственный файл index.php (фронт-контроллер) обрабатывает все запросы. .htaccess нужен, чтобы все запросы к несуществующим файлам и каталогам передавались этому файлу, а не возвращали 404 напрямую.

Базовый блок фронт-контроллера — одинаковый для большинства фреймворков:

.htaccessкопировать
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [L,QSA]
  • RewriteCond %{REQUEST_FILENAME} !-f — не перенаправлять реально существующие файлы (CSS, JS, картинки).
  • RewriteCond %{REQUEST_FILENAME} !-d — не перенаправлять реально существующие каталоги.
  • [L,QSA] — последнее правило, сохранить строку запроса (?foo=bar).
  • Если сайт в подкаталоге (/myapp/), добавьте RewriteBase /myapp/ перед правилами.
  • Требует включённого mod_rewrite и AllowOverride FileInfo (или AllowOverride All) в конфиге Apache — /errors/ → раздел 4.

2. Laravel

Laravel поставляется с готовым public/.htaccess. Document root сервера должен указывать на папку public/ — это правильная и рекомендуемая настройка. Файл .htaccess находится в public/ и уже включён в репозиторий.

.htaccessкопировать
<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews -Indexes
    </IfModule>

    RewriteEngine On

    # Редирект на HTTPS (если нужен — раскомментировать)
    # RewriteCond %{HTTPS} off
    # RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

    # Отправить Authorization в PHP через переменную окружения
    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

    # Редирект на URL без завершающего слеша (если BASE задан)
    RewriteCond %{REQUEST_URI} ^/(.+)/$
    RewriteRule ^ %{ENV:BASE}/%1 [L,R=301]

    # Передать запрос в index.php, если файл/каталог не существует
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]
</IfModule>

Если хостинг не позволяет задать public/ как document root, добавьте в корне проекта дополнительный .htaccess, который перенаправит запросы в public/ и защитит служебные файлы:

.htaccessкопировать
# Перенаправить всё в public/
RewriteEngine On
RewriteRule ^$ public/ [L]
RewriteRule ^(.*)$ public/$1 [L]

# Защита .env и служебных файлов — они не должны быть снаружи
<FilesMatch "^\.env">
    Require all denied
</FilesMatch>

# Нельзя обращаться к vendor/ напрямую
RedirectMatch 404 ^/vendor/
RedirectMatch 404 ^/storage/
RedirectMatch 404 ^/bootstrap/cache/
  • Грабля: Authorization не доходит до PHP. На некоторых хостингах с PHP-FPM заголовок Authorization (для HTTP Basic / Bearer-токенов API) не передаётся. Решение: строка RewriteCond %{HTTP:Authorization} . + RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] уже есть в стандартном public/.htaccess. Если всё равно не работает — добавьте CGIPassAuth On (Apache 2.4.13+).
  • Грабля: 500 после деплоя. Убедитесь, что в .htaccess нет php_value / php_flag — на FPM они дают 500. Настройки PHP на FPM задаются в .user.ini — подробно /errors/ → раздел 2.
  • Грабля: document root не на public/. Без корневого .htaccess (пример выше) браузер сможет обратиться к /vendor/, /.env, /storage/ — исходники наружу. Проверить — аудит безопасности.
  • Проверить синтаксис — линтер .htaccess; разобрать построчно — объяснить .htaccess.

3. Symfony

В Symfony Flex document root также должен указывать на public/. Если вы устанавливаете пакет symfony/apache-pack, он автоматически создаёт public/.htaccess с большим блоком (включая DirectoryIndex index.php, FallbackResource /index.php и RewriteRule). Без пакета — используйте минимальный фронт-контроллер.

.htaccessкопировать
DirectoryIndex index.php

<IfModule mod_negotiation.c>
    Options -MultiViews
</IfModule>

<IfModule mod_rewrite.c>
    RewriteEngine On

    RewriteCond %{REQUEST_URI}::$0 ^(/.+)/(.*)::\2$
    RewriteRule .* - [E=BASE:%1]

    RewriteCond %{HTTP:Authorization} .
    RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

    RewriteCond %{ENV:REDIRECT_STATUS} =""
    RewriteRule ^index\.php(?:/(.*)|$) %{ENV:BASE}/$1 [R=301,L]

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ %{ENV:BASE}/index.php [L]
</IfModule>

<IfModule !mod_rewrite.c>
    <IfModule mod_alias.c>
        RedirectMatch 307 ^/$ /index.php/
    </IfModule>
</IfModule>

Если apache-pack не используется — достаточно минимального фронт-контроллера из раздела 1 в папке public/. Для корня проекта (если docroot не public/) — тот же приём, что у Laravel: RewriteRule ^(.*)$ public/$1 [L] плюс защита .env и vendor/.

  • Symfony по умолчанию рассчитан на public/ как docroot — по возможности именно так и настраивайте хостинг.
  • Все файлы вне public/ (config/, src/, vendor/, .env) не должны быть доступны напрямую; если docroot на корне — добавьте защиту через RedirectMatch 404 или <FilesMatch>.
  • Разобрать сгенерированный apache-pack файл построчно — объяснить .htaccess.

4. Joomla

Joomla поставляется с файлом htaccess.txt в корне. После установки его нужно переименовать в .htaccess — это обязательный шаг, без него ЧПУ (SEF URL) не заработают. Переименуйте через FTP/SSH или файловый менеджер панели хостинга.

.htaccessкопировать
Options +FollowSymLinks
Options -Indexes

<IfModule mod_rewrite.c>
    RewriteEngine On

    # Не переписывать реально существующие файлы
    RewriteCond %{REQUEST_FILENAME} -f [OR]
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteRule ^ - [L]

    # Не трогать index.php
    RewriteRule ^index\.php$ - [L]

    # Передать все остальные запросы в index.php (SEF URL)
    RewriteRule .* index.php [L]
</IfModule>
  • Главная грабля: не переименован htaccess.txt. Joomla не переименовывает файл автоматически — нужно сделать это руками сразу после установки.
  • После обновления Joomla рекомендуется сравнить свой .htaccess с обновлённым htaccess.txt — новые версии могут содержать исправленные правила.
  • Не редактируйте блок между маркерами # -- Joomla! core SEF Section. вручную без необходимости — при обновлении правила могут перезаписаться.
  • Включить SEF URL в Joomla: Глобальная конфигурация → SEO-настройки → «Использование URL-оптимизации» = Да + «Перезапись URL» = Да.
  • Проверить синтаксис — линтер .htaccess.

5. Drupal

Drupal поставляется с большим .htaccess в корне (для Drupal 7/8/9/10). Он включает Options, AddEncoding, ErrorDocument, защиту .txt/.md/vendor и блок clean-URLs. Drupal 8 и новее рекомендует web/ как document root.

.htaccessкопировать
<IfModule mod_rewrite.c>
    RewriteEngine On

    # Не переписывать реально существующие файлы и каталоги
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    # Не переписывать запросы к файлам установки
    RewriteCond %{REQUEST_URI} !=/favicon.ico

    # Передать всё в index.php (clean URLs)
    RewriteRule ^ index.php [L]
</IfModule>
  • Не редактируйте файл .htaccess из дистрибутива напрямую — при обновлении он будет перезаписан. Свои правила добавляйте в отдельный файл выше по дереву или через sites/default/.
  • Drupal 8+ с web/ как docroot: убедитесь, что sites/, vendor/, .env находятся вне web/ и недоступны снаружи.
  • Clean URLs в Drupal активируются в настройках: Конфигурация → Чистые URL.
  • Разобрать стандартный Drupal .htaccess построчно — объяснить .htaccess.

6. 1С-Битрикс

1С-Битрикс размещает собственный .htaccess при установке. Ключевая особенность: ЧПУ направляются через /bitrix/urlrewrite.php, а не через стандартный index.php. Также в комплект входят защита папки upload/ от выполнения PHP и блоки с php_value-настройками для shared-хостинга.

.htaccessкопировать
Options -Indexes
ErrorDocument 404 /404.php

<IfModule mod_rewrite.c>
    RewriteEngine On

    # Не перенаправлять реально существующие файлы и каталоги
    RewriteCond %{REQUEST_FILENAME} -f [OR]
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteRule ^ - [L]

    # ЧПУ Битрикса через urlrewrite.php
    RewriteRule ^(.*)$ /bitrix/urlrewrite.php [L]
</IfModule>

# Запрет выполнения PHP в папке upload/
<IfModule mod_rewrite.c>
    RewriteRule ^upload/(.*)\.php$ - [F,L]
</IfModule>

# Альтернативный вариант (через FilesMatch в upload/.htaccess):
# <FilesMatch "\.ph(p[0-9]?|tml|ar)$">
#     Require all denied
# </FilesMatch>
  • Грабля: php_value на PHP-FPM. Стандартный Битрикс-.htaccess содержит блок с php_value / php_flag-настройками для работы с mod_php. На PHP-FPM эти директивы дают 500. Удалите или закомментируйте блок php_value, настройки переносите в .user.ini — подробно /errors/ → раздел 2.
  • «Проверка системы» Битрикса. Административная панель Битрикса проверяет наличие нужных правил в .htaccess — если правила удалены или изменены, она сообщит об ошибке.
  • Папка upload/ должна быть защищена от выполнения PHP (пример выше); то же касается upload/ внутри подсайтов.
  • Аудит безопасности — аудит .htaccess; справочник защиты файлов — /security/ → раздел 2.

7. Yii2

Yii2 использует каталог web/ как document root (аналог public/ у Laravel). Файл web/.htaccess включён в шаблон приложения.

.htaccessкопировать
Options +FollowSymLinks
IndexIgnore */*

<IfModule mod_rewrite.c>
    RewriteEngine on

    # Не перенаправлять реально существующие файлы и каталоги
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d

    # Передать всё в index.php
    RewriteRule . index.php [L]
</IfModule>

Файлы вне web/ (config/, runtime/, vendor/, .env) не должны быть доступны снаружи. Если хостинг задаёт docroot на корень проекта, добавьте в корень:

.htaccessкопировать
RewriteEngine On
RewriteRule ^$ web/ [L]
RewriteRule ^(.*)$ web/$1 [L]

<FilesMatch "^\.env">
    Require all denied
</FilesMatch>
RedirectMatch 404 ^/vendor/
RedirectMatch 404 ^/runtime/
  • Document root лучше настраивать на web/ — это правильнее и безопаснее, чем корень проекта.
  • Проверить настройки URL-менеджера Yii: 'enablePrettyUrl' => true, 'showScriptName' => false в конфигурации компонента urlManager.
  • Проверить синтаксис — линтер .htaccess.

8. OpenCart

OpenCart поставляется с готовым .htaccess в корне. Он включает маршрутизацию через параметр _route_ и закомментированные блоки для gzip и кэша — их можно раскомментировать для ускорения.

.htaccessкопировать
Options +FollowSymlinks
Options -Indexes

<IfModule mod_rewrite.c>
    RewriteEngine On

    # Не трогать index.php
    RewriteRule ^index\.php - [L]

    # Защита system/ и config.php
    RewriteRule ^system/ - [F,L]
    RewriteRule ^config\.php - [F,L]
    RewriteRule ^admin/config\.php - [F,L]

    # Не перенаправлять реально существующие файлы и каталоги
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d

    # Маршрутизация OpenCart через _route_
    RewriteRule ^([^?]*) index.php?_route_=$1 [L,QSA]
</IfModule>
  • Маршрутизация OpenCart использует параметр _route_ — этим он отличается от стандартного фронт-контроллера большинства фреймворков.
  • Закомментированные блоки gzip/кэша в стандартном .htaccess OpenCart можно раскомментировать для ускорения сайта — подробно /performance/.
  • Защита system/ и config.php: убедитесь, что они недоступны снаружи — /security/ → раздел 2.

9. CodeIgniter 4

CodeIgniter 4 использует папку public/ как document root (аналогично Laravel). Файл public/.htaccess включён в дистрибутив.

.htaccessкопировать
<IfModule mod_rewrite.c>
    Options -Indexes

    RewriteEngine On

    # Не перенаправлять реально существующие файлы и каталоги
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d

    # Передать всё в index.php
    RewriteRule ^(.*)$ index.php/$1 [L]
</IfModule>

<IfModule !mod_rewrite.c>
    # Если mod_rewrite недоступен — использовать index.php?/$1
    ErrorDocument 404 index.php
</IfModule>
  • Обратите внимание на index.php/$1 (PATH_INFO) — это стандарт CodeIgniter 4; для совместимости с некоторыми хостингами иногда меняют на index.php?/$1.
  • Файлы вне public/ (app/, vendor/, .env) не должны быть доступны снаружи. При docroot на корне — добавьте RewriteRule ^(.*)$ public/$1 [L] и защиту .env.
  • Проверить синтаксис — линтер .htaccess.

10. OctoberCMS и другие фреймворки на Laravel

OctoberCMS, Statamic, Craft CMS и другие системы, построенные на Laravel или с аналогичной архитектурой, используют тот же паттерн: public/.htaccess с фронт-контроллером на index.php и защита служебных файлов (app/, storage/, .env) вне public/.

Общий совет для таких систем: берите .htaccess из официальной документации фреймворка или из репозитория, не пишите с нуля. Большинство из них уже содержат нужные правила, проверенные сообществом.

.htaccessкопировать
<IfModule mod_rewrite.c>
    Options -Indexes

    RewriteEngine On

    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]
</IfModule>

Для корня проекта (если docroot не на public/) — защитите .env, vendor/, storage/:

.htaccessкопировать
<FilesMatch "^\.env">
    Require all denied
</FilesMatch>

RedirectMatch 404 ^/vendor(/|$)
RedirectMatch 404 ^/storage(/|$)
RedirectMatch 404 ^/config(/|$)
  • Если .env доступен снаружи — это критическая уязвимость: он содержит пароли базы данных, секретные ключи и другие данные. Проверить — аудит безопасности .htaccess.
  • Подробная защита файлов — /security/ → раздел 2.

11. Частые проблемы у всех фреймворков

Несколько проблем встречаются независимо от того, какой фреймворк вы используете.

  • После переноса на хостинг все маршруты дают 404. Причины: .htaccess отсутствует или не скопировался (он часто скрытый файл); mod_rewrite не включён; AllowOverride не разрешает .htaccess; неверный RewriteBase (сайт в подкаталоге). Подробно — /errors/ → раздел 4. Фреймворк-специфика ЧПУ (Laravel/Symfony/Joomla/…) — хаб «.htaccess для CMS и фреймворков».
  • 500 после деплоя. Чаще всего — php_value / php_flag в .htaccess при PHP-FPM. Также: директива Options при AllowOverride без флага Options. Удалите строки php_value / php_flag, настройки PHP переносите в .user.ini. Подробно — /errors/ → раздел 2.
  • Document root не на public/. Если хостинг не позволяет сменить docroot, добавьте в корень проекта RewriteRule ^(.*)$ public/$1 [L] и RewriteRule ^$ public/ [L]. Обязательно защитите vendor/, .env, config/ — иначе исходники доступны снаружи. Проверить — /security/, аудит.
  • Authorization не доходит до API. На некоторых конфигурациях Apache + PHP-FPM заголовок Authorization не передаётся в $_SERVER. Решение: CGIPassAuth On (Apache 2.4.13+) или RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] в .htaccess.
  • Двойной слеш или trailing-slash петля. Правило добавляет слеш, другое правило его убирает — бесконечный редирект. Подробно — /errors/ → раздел 5.
  • Разобрать чужой .htaccess фреймворка построчно — инструмент «Объяснить .htaccess».

12. Чеклист: .htaccess фреймворка за 5 минут

  1. .htaccess на месте (не скрытый файл, не htaccess.txt), маршруты работают? — /errors/ → раздел 4, /check/
  2. mod_rewrite включён, AllowOverride All или хотя бы AllowOverride FileInfo? — /errors/ → раздел 4
  3. Document root на public/ (или web/), либо в корне есть RewriteRule ^(.*)$ public/$1 [L]? — раздел 2, раздел 7
  4. .env / vendor/ / config/ / storage/ недоступны снаружи? — /security/, /audit/
  5. php_value / php_flag убраны из .htaccess, если используется PHP-FPM? — /errors/ → раздел 2
  6. CGIPassAuth On (или RewriteRule-workaround) настроен, если используете HTTP Basic или Bearer в API? — раздел 11
  7. Синтаксис .htaccess проверен (/check/), аудит безопасности пройден (/audit/)?