Убираем .php из адресов страниц

Раздел: Веб-разработка -> Управление URL

Способы удаления .php из ссылок

Основное решение - использование модуля mod_rewrite в Apache или аналогичных директив в Nginx. Правила преобразуют URL без расширения во внутренний запрос к PHP-файлу. Это позволяет создавать чистые адреса, удобные для пользователей и поисковых систем.

Пример конфигурации для Apache (.htaccess в корне сайта):

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

ссылки без php (создание ссылок без расширения .php)

Пояснение:

  • RewriteEngine On - включает обработку.
  • RewriteCond %{REQUEST_FILENAME} !-f - исключает существующие файлы.
  • RewriteCond %{REQUEST_FILENAME} !-d - исключает существующие директории.
  • RewriteRule ^(.+)$ index.php?page=$1 [L,QSA] - перенаправляет все запросы (кроме файлов/папок) на index.php с параметром page, передавая исходный URL. Флаги L (последнее правило), QSA (добавление существующих query-параметров).

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

  • Ошибка 500 - не включён модуль mod_rewrite. Проверить командой apache2ctl -M или через панель управления хостингом.
  • Запросы к реальным файлам не обрабатываются - убедиться, что RewriteCond проверяют существование файла и директории.
  • Пути к CSS/JS/images ломаются - указать базовый URL в HTML <base href="/"> или настроить RewriteRule для статики.
  • Циклическая переадресация - проверить, что в RewriteRule не указан путь, совпадающий с index.php.

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

В Nginx используется директива try_files и rewrite. Пример конфигурации для серверного блока (server):

location / {
    try_files $uri $uri/ /index.php?page=$uri&$args;
}
location ~ \.php$ {
    fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}

try_files проверяет наличие реального файла или директории, если их нет - передаёт запрос в index.php с параметром page. Важно, чтобы блок location ~ \.php$ обрабатывал сам PHP-файл, иначе запрос уйдёт на статику.

Проблемы: если try_files неверно указан, возможен бесконечный редирект. Проверить логи Nginx (error.log). Убедиться, что путь /index.php действительно обрабатывается через FastCGI.

Как обрабатывать все запросы через единую точку входа на PHP?

Вместо веб-сервера можно реализовать роутинг внутри PHP. Требуется направить все запросы на index.php (как в первом варианте Apache). Сам код PHP:

$page = $_GET['page'] ?? 'home';
$page = rtrim($page, '/');
$page = filter_var($page, FILTER_SANITIZE_URL);
// Далее маршрутизация
switch ($page) {
    case 'about':
        require 'about.php';
        break;
    case 'contact':
        require 'contact.php';
        break;
    default:
        require 'home.php';
}

Теперь URL /about приводит к загрузке about.php. Необходимо создать соответствующие PHP-файлы или включить логику контроллеров.

Ошибки: отсутствие обработки 404 - добавить проверку существования файла. Проблемы с безопасностью - санитизировать параметр page, не допускать path traversal. Также нужно решить вопрос с query-параметрами.

Как избежать .php в фреймворках (Laravel, Symfony)?

Современные фреймворки по умолчанию скрывают расширение. Например, Laravel использует public/index.php как единую точку входа, а конфигурация веб-сервера уже настроена на перенаправление всех запросов к этому файлу. Достаточно следовать документации по установке. Вручную править ничего не требуется.

Ошибка: если не настроен .htaccess в папке public, Laravel выдаст 404. Проверить наличие файла и включённый модуль mod_rewrite.

Можно ли физически создавать папки без .php?

Теоретически можно создать папку с именем страницы и поместить в неё файл index.php. Например, папка /about/ с index.php внутри. Тогда URL /about/ будет работать. Но для каждой страницы придётся создавать отдельную папку, что неудобно при масштабировании. Подходит только для статичных сайтов с малым числом страниц.

Проблемы: дублирование контента (если доступен и /about без слеша - может вернуть другой ответ). Лишние файлы на сервере. Не рекомендуется для динамических проектов.

Дополнительные примеры конфигураций

Сложное правило Apache с исключениями

Правило ниже запрещает прямой доступ к PHP-файлам (кроме index.php), обрабатывает поддомены, добавляет HTTPS.

Пример
RewriteEngine On
RewriteBase /

# Принудительный HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]

# Запрет прямого доступа к .php (кроме index)
RewriteCond %{REQUEST_URI} \.php$ [NC]
RewriteCond %{REQUEST_URI} !^/index\.php$
RewriteRule ^ - [F,L]

# ЧПУ
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-zA-Z0-9-/]+)$ index.php?route=$1 [L,QSA]

Результат: при запросе /about/team сервер возвращает контент из index.php?route=about/team. При прямом обращении к /secret.php - ошибка 403 Forbidden.

Nginx с кэшированием и статикой

Пример
location / {
    try_files $uri $uri/ /index.php?$args;
}

# Статические файлы с долгим кэшированием
location ~* \.(?:ico|css|js|gif|jpe?g|png|webp|svg)$ {
    expires 30d;
    add_header Cache-Control "public, immutable";
    try_files $uri /index.php?$args;
}

location ~ \.php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
}

Результат: запрос /style.css обслуживается напрямую, /contacts уходит на PHP-обработчик. Кэширование статики ускоряет загрузку.

PHP роутинг с поддержкой вложенных путей

Пример
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$uri = trim($uri, '/');
$segments = explode('/', $uri);

$controller = $segments[0] ?? 'home';
$action = $segments[1] ?? 'index';
$params = array_slice($segments, 2);

// Пример безопасного вызова
$class = 'Controllers\\' . ucfirst($controller);
if (class_exists($class)) {
    $instance = new $class();
    if (method_exists($instance, $action)) {
        call_user_func_array([$instance, $action], $params);
        exit;
    }
}
http_response_code(404);
echo 'Страница не найдена';

Результат для /user/profile/42: вызывается метод profile класса Controllers\User с параметром 42. Ошибка 404 при отсутствии класса или метода.

Команды для проверки конфигурации

Пример
# Apache: проверить синтаксис
apachectl configtest
# Nginx: проверить
nginx -t
# Перезагрузка без остановки
systemctl reload nginx   # или service apache2 reload

Создание ссылок без расширения .php - comments

En
ссылки без php (php)