Чистые ссылки: конфигурация Apache, Nginx и IIS для удаления index.php

Раздел: Конфигурирование веб-сервера -> Настройка URL и маршрутизация

Основы настройки URL для удаления index.php

Каким образом настроить Apache для скрытия index.php?

Наиболее распространённый способ

Apache использует модуль mod_rewrite для преобразования URL. Основная цель - перенаправлять запросы, не указывающие на реальный файл, на index.php.


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

убрать index php (удаление index.php из url)

Пояснение:

  • RewriteEngine On - включает обработку правил.
  • RewriteCond %{REQUEST_FILENAME} !-f - проверяет, что запрошенный файл не существует.
  • RewriteCond %{REQUEST_FILENAME} !-d - проверяет, что запрошенная директория не существует.
  • RewriteRule ^(.*)$ index.php/$1 [L] - перенаправляет всё на index.php, добавляя URI после слэша.

Также можно использовать вариант без захвата пути:


RewriteRule .* index.php [L]

Цель: все нефизические URL обрабатываются через index.php, что даёт чистые адреса без принудительного добавления index.php.

Типичные ошибки и их устранение:

  • Ошибка 404: возможно, модуль mod_rewrite не включён. Команда sudo a2enmod rewrite в Debian/Ubuntu.
  • Циклический редирект: правило не проверяет индексный файл - добавьте проверку на index.php: RewriteCond %{REQUEST_URI} !^index\.php.
  • Не работают статические файлы (CSS, JS, картинки): убедитесь, что RewriteCond проверяет реальные файлы, или укажите корневую директорию RewriteBase /.

Как удалить index.php в среде Nginx?

Nginx не использует .htaccess, настройка выполняется в конфигурационном файле сервера. Пример:


location / {
    try_files $uri $uri/ /index.php?$query_string;
}

Пояснение: директива try_files пытается сначала отдать статический файл ($uri), затем директорию ($uri/), и если ничего не найдено - передаёт запрос на index.php с исходным query string.

Возникающие проблемы:

  • Если PHP обрабатывается через fastcgi, необходимо убедиться, что блок location ~ \.php$ определён выше общего location.
  • Параметр $uri/ может вызвать нежелательное перенаправление на существующие директории; можно использовать только try_files $uri /index.php?$uri.
  • Необходимо перезагружать конфигурацию: sudo nginx -s reload.

Как настроить IIS для скрытия index.php?

В IIS используется модуль URL Rewrite. Правило описывается в файле web.config:


<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <rule name="Remove index.php" stopProcessing="true">
                    <match url=".*" />
                    <conditions>
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
                    </conditions>
                    <action type="Rewrite" url="index.php/{R:0}" />
                </rule>
            </rules>
        </rewrite>
    </system.webServer>
</configuration>

Пояснение: правило срабатывает, если запрошенный файл или директория не существуют. URL переписывается так, что путь передаётся в index.php.

Ошибки:

  • Модуль URL Rewrite не установлен - скачать с официального сайта Microsoft. После установки требуется перезапуск IIS.
  • Ошибка 500 при неправильном синтаксисе - проверьте кодировку UTF-8, отсутствие лишних тегов.

Как поступить с чистым URL, если доступ к настройкам сервера ограничен?

Использовать встроенный PHP роутер из php.ini или файл router.php. Запуск сервера с опцией:


$ php -S localhost:8000 index.php

В этом режиме все запросы обрабатываются через index.php, если не найден статический файл. Однако это не подходит для продакшена.

Другой способ - написать собственный PHP-роутер, который проверяет $_SERVER['REQUEST_URI'] и подключает нужные контроллеры. Пример:


$request = $_SERVER['REQUEST_URI'];
if (preg_match('/\.(?:css|js|png|jpg)$/', $request)) {
    return false;
}
// Перенаправление на единую точку входа
$_GET['_url'] = ltrim($request, '/');
require 'index.php';

Цель: достичь чистых URL без модификации конфигурации веб-сервера, подходит для локальной разработки.

Недостатки:

  • Производительность ниже, чем при настройке сервера.
  • Требует обработки статических файлов внутри PHP, что замедляет отдачу.
  • Не решает проблемы SEO и красоты URL в продакшене.

Дополнительные и нестандартные примеры кода

Расширенный .htaccess для многосайтовой установки (WordPress)

Пример

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /

# Если запрос относится к реальному файлу или директории, не переписывать
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

# Исключить путь к подсайтам (например, /blog/)
RewriteRule !^(blog|other) /index.php [L]

# Если WordPress в подпапке
RewriteRule ^blog/(.*)$ blog/index.php?url=$1 [QSA,L]
</IfModule>
Результат: URL вида example.com/blog/статья обрабатывается blog/index.php без index.php в строке.

Nginx: обработка index.php для нескольких корней (Microservices)

Пример

server {
    listen 80;
    server_name example.com;

    root /var/www/html;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location /api/ {
        alias /var/www/api/public;
        try_files $uri $uri/ /api/index.php?$args;
    }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}
Обращение к /api/users передаётся в /api/index.php, URL остаётся чистым.

IIS: правило с проверкой на index.php в URL (предотвращение зацикливания)

Пример

<rule name="Remove index.php" stopProcessing="true">
    <match url=".*" />
    <conditions logicalGrouping="MatchAll">
        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
        <add input="{URL}" pattern="^/index\.php" negate="true" />
    </conditions>
    <action type="Rewrite" url="index.php/{R:0}" appendQueryString="true" />
</rule>
Правило не применяется, если запрос уже содержит index.php, разрывая цикл.

PHP-роутер для встроенного сервера с обработкой ошибок 404

Пример

// router.php
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);

$allowedExtensions = ['css', 'js', 'png', 'jpg', 'gif', 'ico'];
$ext = pathinfo($uri, PATHINFO_EXTENSION);

if (in_array($ext, $allowedExtensions) && file_exists(__DIR__ . $uri)) {
    return false; // отдаём статический файл
}

// Прочие запросы - передаём в index.php
$_SERVER['SCRIPT_NAME'] = '/index.php';
require __DIR__ . '/index.php';
Запуск: php -S 0.0.0.0:8080 router.php
URL /about обрабатывается через index.php без index.php в строке.

Удаление index.php из URL - comments

En
убрать index php (php)