Настройка RewriteCond в .htaccess для PHP: проверка существования и перенаправление запросов

Раздел: Администрирование -> Настройка веб-сервера

Правило RewriteCond для PHP в .htaccess

Основное решение: перенаправление всех несуществующих файлов на главный PHP-обработчик

Наиболее часто используемая конструкция - проверка, что запрошенный файл или директория не существуют, после чего запрос передаётся на PHP-скрипт (например, index.php). Это основа многих современных веб-приложений с «человекопонятными» URL.


RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?route=$1 [QSA,L]
  

Mod rewrite index php (настройка mod_rewrite для index.php)

Пояснение шагов:

  • RewriteEngine On - включает модуль mod_rewrite.
  • RewriteCond %{REQUEST_FILENAME} !-f - проверяет, что запрошенный путь не является существующим файлом.
  • RewriteCond %{REQUEST_FILENAME} !-d - проверяет, что путь не является существующей директорией.
  • RewriteRule ^(.*)$ index.php?route=$1 [QSA,L] - если условия выполнены, перенаправляет запрос на index.php, передавая исходный URI как параметр route. Флаги QSA (Query String Append) и L (Last) завершают обработку.

Типичные ошибки и их решение:

  • Ошибка 500 (Internal Server Error) - часто возникает из-за неверного синтаксиса или отсутствия модуля rewrite. Проверьте, что модуль включён (команда a2enmod rewrite в Debian/Ubuntu).
  • Циклический редирект (бесконечный цикл) - если правило перенаправляет на уже обработанный URL. Решение: убедиться, что RewriteCond правильно исключает сам целевой скрипт (например, добавить условие !-f или !-d).
  • Параметры запроса не передаются - без флага QSA они теряются. Используйте [QSA] или [QSA,L].

Как разрешить доступ к реальным файлам, а все остальные запросы передать PHP-обработчику?

Этот вариант противоположен предыдущему: если файл существует, его отдаёт веб-сервер напрямую, иначе запрос идёт на PHP.


RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^(.*)$ index.php [L]
  

Upstream php fpm (настройка upstream для php-fpm в nginx)

Пояснение: Первые два условия проверяют, что файл или директория существуют. Если условие верно, RewriteRule с минусом (^ -) ничего не делает и флаг L останавливает обработку. В противном случае запрос перенаправляется на index.php.

Проблема: При использовании этого подхода возможно случайное перенаправление запросов к PHP-файлам, которые должны обрабатываться напрямую. Решение - уточнить условия: исключить определённые расширения или пути.

Как проверить, что файл является символической ссылкой, и обработать иначе?

Директива RewriteCond %{REQUEST_FILENAME} -l позволяет проверить, является ли запрошенный путь символической ссылкой. Пример: перенаправление ссылок на специальный скрипт.


RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -l
RewriteRule ^(.+)$ symlink_handler.php?file=$1 [L]
  

запустить локальный сервер php (запуск локального сервера php)

Пояснение: Если путь является символической ссылкой, запрос обрабатывается скриптом symlink_handler.php с передачей имени файла. Для остальных файлов можно добавить другие правила.

Ошибка: Символическая ссылка может указывать на файл вне DocumentRoot. Убедитесь, что веб-сервер настроен на следование символическим ссылкам (опция FollowSymLinks в <Directory>).

Как защитить от прямого доступа к PHP-файлам в определённой папке?

Используется проверка расширения файла и перенаправление на страницу ошибки или главный обработчик.


RewriteEngine On
RewriteCond %{REQUEST_URI} \.php$
RewriteCond %{REQUEST_URI} !^/index\.php$
RewriteRule ^(.*)$ /error.php [L]
  

Php non thread safe (php non-thread-safe (не потокобезопасная версия))

Пояснение: Первое условие проверяет, что URI заканчивается на .php. Второе исключает сам файл index.php (чтобы не блокировать его). Если оба условия верны, запрос перенаправляется на /error.php. Это может использоваться для защиты скриптов, которые не должны вызываться напрямую.

Проблема: Блокируются все PHP-файлы, включая те, что нужны для AJAX-запросов. Решение: добавить исключения для конкретных файлов или папок через дополнительные RewriteCond с ! (отрицание).

Как проверить, что файл не пустой (имеет ненулевой размер)?

Условие RewriteCond %{REQUEST_FILENAME} -s истинно, если файл существует и его размер больше 0. Полезно для замены пустых файлов на сгенерированный контент.


RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-s
RewriteRule \.(jpg|png|gif)$ placeholder.php?file=$1 [L]
  

Rewritecond request filename php (правило rewritecond для php в .htaccess)

Пояснение: Если запрашивается изображение с расширением jpg, png или gif, но файл пустой (или не существует - !-s вернёт true), запрос обрабатывается скриптом-заглушкой, который может отдать дефолтное изображение.

Ошибка: !-s вернёт true также для несуществующих файлов. Если нужно различать несуществующий и пустой, используйте комбинацию -f и -s.

Как проверить доступность URL через внутреннюю подстановку (флаг -U)?

Флаг -U доступен только в Apache 2.4+. Он проверяет, что внутренний URI (после применения всех предыдущих RewriteRule) обрабатывается успешно (не возвращает 404). Пример - «красивые» URL с fallback на страницу ошибки, если контроллер неопределён.


RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ index.php?url=$1 [L]
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{REQUEST_URI} !^/index\.php$
RewriteCond %{REQUEST_URI} -U
RewriteRule ^(.*)$ /custom-404.php [L]
  

Пояснение: Сначала несуществующие запросы передаются на index.php. Затем, если после внутреннего перенаправления (по флагу REDIRECT_STATUS) URI по-прежнему недоступен (-U), происходит редирект на кастомную 404 страницу.

Проблема: Флаг -U может снизить производительность, так как выполняет дополнительный внутренний запрос. Используйте его только при необходимости и следите за нагрузкой.

- Var www html index php (размещение index.php в var/www/html)
- веб серверы php (веб-серверы для php)

Расширенные примеры использования RewriteCond для PHP

Пример 1: Перенаправление с проверкой существования файла и папки, включая защиту от цикла

Код для .htaccess в корне сайта, который передаёт все запросы на index.php, кроме существующих файлов/папок и самого index.php.

Пример

RewriteEngine On
RewriteBase /
# Исключаем сам скрипт, чтобы избежать зацикливания
RewriteCond %{REQUEST_URI} !^/index\.php$
# Проверяем, что файл или папка не существуют
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Перенаправляем с сохранением строки запроса
RewriteRule ^(.*)$ index.php?/$1 [L,QSA]
  

Результат: Запрос /about обрабатывается как /index.php?/about, и PHP-скрипт может разобрать URL. Запрос /style.css (если файл есть) отдаётся напрямую.

Пример 2: Условное перенаправление на PHP-скрипт в зависимости от типа устройства (User-Agent)

Используется для мобильной версии: если файл не существует и User-Agent содержит «Mobile», запрос идёт на m.index.php, иначе на desktop версию.

Пример

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{HTTP_USER_AGENT} "Mobile|Android|iPhone" [NC]
RewriteRule ^(.*)$ m.index.php?route=$1 [L]

# Отдельное правило для остальных (десктоп)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?route=$1 [L]
  

Результат: Пользователь с мобильного браузера увидит мобильную версию, если файла не существует; иначе - стандартную.

Пример 3: Защита PHP-файлов с проверкой IP-адреса администратора

Доступ к /admin/ только для определённого IP; в противном случае - перенаправление на логин-скрипт.

Пример

RewriteEngine On
RewriteCond %{REQUEST_URI} ^/admin/
RewriteCond %{REMOTE_ADDR} !^192\.168\.1\.100$
RewriteRule ^(.*)$ /login.php?redirect=$1 [L]
  

Результат: Если IP не совпадает с 192.168.1.100, пользователь перенаправляется на страницу входа.

Пример 4: Перенаправление старых URL на новые через PHP с сохранением 301 статуса

Используется внешний редирект (R=301) для SEO, при этом проверяется, что запрос соответствует старому шаблону.

Пример

RewriteEngine On
RewriteCond %{REQUEST_URI} ^/old/(.*)\.html$
RewriteRule ^old/(.*)\.html$ /new.php?slug=$1 [R=301,L]
  

Результат: Запрос /old/article.html отправляет браузеру код 301 и перенаправляет на /new.php?slug=article.

правило RewriteCond для PHP в .htaccess - comments

En
Rewritecond request filename php (php)