Убираем .php из адресов страниц
Способы удаления .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 как единую точку входа, а конфигурация веб-сервера уже настроена на перенаправление всех запросов к этому файлу. Достаточно следовать документации по установке. Вручную править ничего не требуется.
Можно ли физически создавать папки без .php?
Теоретически можно создать папку с именем страницы и поместить в неё файл index.php. Например, папка /about/ с index.php внутри. Тогда URL /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