У лютому 2009 року я зберіг нотатку про формування зрозумілих URL для динамічних сторінок Apache/PHP. Джерелом був матеріал woweb.ru/publ/36-1-0-336. У ньому розглядали чотири підходи: обробник помилки 404, MultiViews, ForceType і mod_rewrite.
Нижче збережено початкові фрагменти коду як історичні приклади. Вони залежать від конфігурації Apache та способу підключення PHP; некоректні конструкції окремо пояснено.
1. Обробник ErrorDocument
ErrorDocument 404 script.php
Старий підхід пропонував обробляти вигаданий URL у скрипті, викликаному замість відсутньої сторінки. Наведений рядок не є готовим маршрутизатором: значення ErrorDocument має відповідати синтаксису Apache. Для наявної сторінки та справді відсутнього ресурсу потрібні різні результати обробки й HTTP-статуси.
2. MultiViews
Options Multiviews
У нотатці припускали, що шлях на кшталт /one/two/three буде зіставлено з файлом one.php, а залишок обробить скрипт. Насправді MultiViews належить до узгодження вмісту: добір варіанта залежить від розширень і налаштувань. Це пояснює документація Apache. Такий механізм не є універсальною заміною маршрутизації.
3. ForceType та обробник PHP
<filesmatch index="">
ForceType application/x-httpd-php
</filesmatch>
Цей блок у збереженому HTML мав некоректний запис секції FilesMatch, тому його не можна копіювати як чинну конфігурацію. ForceType задає тип вмісту; використання спеціального MIME-типу для запуску PHP залежало від історичної поведінки модулів. Apache рекомендує уникати такого покладання на «магічні» типи та налаштовувати обробник явно. Для PHP-FPM потрібна конфігурація відповідного способу підключення.
4. Правила mod_rewrite
RewriteEngine On
Options +FollowSymlinks
RewriteBase /
RewriteRule ^index/(.*)$ /index.php/$1
Модуль переписує шлях index/... у /index.php/.... Це не обов'язково зовнішнє перенаправлення браузера: переписування може бути внутрішнім. Контекст правила й прапорці визначають результат; дивіться mod_rewrite. Директива RewriteEngine сама собою не обмежує правила лише поточним каталогом.
У джерелі було й комбіноване налаштування:
RewriteEngine On
RewriteBase /
RewriteRule ^index/(.*)$ /index.php/$1
<filesmatch index.php="">
ForceType application/x-httpd-php
</filesmatch>
Воно містить таку саму проблему запису FilesMatch. Приклад із сайтом webshops.ru пояснював задум: запит /index/webshops обробляє index.php, який визначає потрібну сторінку за URI. Це ілюстрація маршруту з давнього матеріалу, а не перевірена конфігурація цього сайту сьогодні. Замість старої змінної $REQUEST_URI у сучасному PHP зазвичай використовують $_SERVER['REQUEST_URI'].
HTTP-заголовки та дата зміни
Початковий матеріал пропонував такі рядки:
Header("HTTP/1.0 200 OK"); //строка нужна только для п. 1
Header("Last-Modified: ".gmdate("D, M d Y H:i:s",filemtime("index.php"))." GMT"); //строка пригодится в любом случае
header() потрібно викликати до фактичного виведення вмісту. Не варто безумовно повертати 200 для будь-якого невідомого URL: відсутній ресурс має залишатися помилкою, інакше можливий soft 404.
Час зміни файла index.php не обов'язково відповідає часу зміни даних усіх сторінок, які він формує. Крім того, у форматі дати старого фрагмента переплутано порядок дня та місяця. Для HTTP-дати потрібен порядок на кшталт D, d M Y H:i:s у GMT; значення Last-Modified має описувати саме відповідне представлення ресурсу — дивіться RFC 9110.
Відносні адреси зображень
У віртуальних каталогах старий матеріал пропонував абсолютні адреси або елемент base у секції head:
<base href="http://ваш_сайт.ru/"></base>
Домен у цьому рядку — заповнювач. За стандартом HTML елемент base не має закривального тега; він впливає на всі відносні URL документа. Після зміни маршрутизації перевірте зображення, стилі, скрипти, форми та звичайні посилання.
Зрозумілі URL корисні для навігації, але динамічний сайт не потрібно «маскувати» під статичний заради самого пошуку. Для поточних рішень орієнтуйтеся на рекомендації Google щодо структури URL та конфігурацію свого сервера.