.htaccess — Как перенаправить URL-адрес в папку, а затем в файл PHP

Я настраиваю систему кэширования для своего блога (не WordPress) и хочу хранить кэшированные файлы в папке posts/, чтобы не заполнять корневую папку файлами постов.

У меня есть файл с именем post.php, который создает эти файлы сообщений, если слаг соответствует фактическому сообщению на другом веб-сайте (я проверяю это с помощью WordPress REST API). Поэтому, когда я посещаю mywebsite.com/slug-to-post и этот URL-адрес не соответствует ни одному из моих файлов на корневом уровне, он откатывается к post.php с использованием FallbackResource post.php в .htaccess, а post.php использует этот слаг для создания кэшированной версии и сохраняет ее, но, поскольку могут быть тысячи постов, я хочу, чтобы файлы хранились не в корневом уровне, а в posts/name-of-the-file.

Таким образом, доступ к этому файлу будет осуществляться через mywebsite.com/posts/slug-to-post, но для целей SEO я все же хочу, чтобы это было mywebsite.com/slug-to-post. Что я должен написать в своем .htaccess, чтобы вернуть любой неизвестный файл в папку posts/, а если файла там нет, снова вернуться к post.php, который хранится на корневом уровне?

Ничего из того, что я пробовал, пока не работает. Для кэширования файлов я использую представленный здесь код: https://phppot.com/php/php-кэш-для-динамических-веб-страниц/

Обновлено: Это мой текущий .htaccess файл:

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

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}/posts/$1 -f
RewriteRule ^([^/]+\.php)$ /posts/$1 [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^[^/]+\.php$ post.php [L]

Как slug-to-post сопоставляется с файлом? Это имя файла?

MrWhite 31.05.2019 03:43

Да, slug-to-post — это имя кэшированного файла, поэтому оно будет выглядеть примерно так: root dir/posts/slug-to-post.php

Alex1337 04.06.2019 15:27

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

MrWhite 05.06.2019 16:37

Это мой текущий .htaccess файл: RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME}\.php -f RewriteRule ^(.*)$ $1.php [NC,L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{DOCUMENT_ROOT}/posts/$1 -f RewriteRule ^([^/]+\.php)$ /posts/$1 [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^[^/]+\.php$ post.php [L] Как я уже упоминал в вашем ответе, теперь mywebsite.com/post-slug.php работает, но mywebsite.com/post-slug выдает ответ 404.

Alex1337 06.06.2019 10:16
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
2
4
183
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы запрашиваете файл формы /<post-slug>, который либо:

  1. Сопоставляется с файлом формы /<post-slug>.php в корне документа.

  2. ИЛИ сопоставляется с кэшированной версией этого файла в форме /posts/<post-slug>.php.

  3. В противном случае запрос должен вернуться к /post.php в корне документа.

Попробуйте что-то вроде следующего (используя mod_rewrite) в дополнение к вашей директиве FallbackResource:

# Disable MultiViews
Options -MultiViews

RewriteEngine On

# 1. Check for file in the document root
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^([^/.]+)$ /$1.php [L]

# 2. Check for cached version in the "/posts" subdirectory
RewriteCond %{DOCUMENT_ROOT}/posts/$1.php -f
RewriteRule ^([^/.]+)$ /posts/$1.php [L]

# 3. Request does not map to a file, so fallback to "/post.php"
FallbackResource /post.php

Это предполагает, что ваш <post-slug> не содержит точек (.). Это позволяет избежать конфликтов со статическим ресурсом или создать ненужную проверку файловой системы после перезаписи запроса на <post-slug>.php. Если <post-slug> может содержать точки, нам нужно изменить RewriteRuleшаблон и добавить дополнительный условие.

NB: MultiViews необходимо отключить, чтобы это работало должным образом (возможно, оно уже отключено на вашем сервере).


RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php [NC,L]

Всего несколько заметок о вашем исходном блоке правил.

  • Если вы сделаете RewriteRuleшаблон более ограничительным, а не совпадающим с что-нибудь (т.е. .*), то вы, вероятно, сможете избежать условия, которое проверяет, что запрос не отображается в каталог файловой системы. (Является ли запрос каталога файловой системы допустимым?)

  • Буквальную точку в RewriteCondтестовая строка (1-й аргумент) не нужно экранировать обратной косой чертой. Это "обычная" строка, а не регулярное выражение.

  • Обратите внимание, что %{REQUEST_FILENAME}.php не обязательно совпадает с (потенциально) переписанным URL-адресом $1.php - это будет зависеть от запроса и файловой системы (поскольку REQUEST_FILENAME вычисляется после, запрос был сопоставлен с файловой системой), но поскольку вы разрешаете что-либо (т.е. .*), то здесь возможна ошибка.

  • Флаг NC лишний, так как RewriteRuleшаблон в любом случае не чувствителен к регистру.

Привет! Спасибо за ваш ответ. Теперь проблема: допустим, в моей папке post-slug.php есть файл posts, путь к которому: mywebsite.com/posts/post-slug.php. Теперь, с новым .htaccess, если я перехожу к mywebsite.com/post-slug, я получаю ответ 404, но если я перехожу к mywebsite.com/post-slug.php, это работает. Поэтому мне нужно добавить .php к 1 доллару, что-то вроде RewriteCond %{DOCUMENT_ROOT}/posts/$1.php -f Как я могу это сделать? Заранее спасибо!

Alex1337 05.06.2019 16:49

Ах, хорошо, это имеет больше смысла. :) Ваши URL-адреса не имеют расширения ... пользователь запрашивает /post-slug (на самом деле они никогда не запрашивают /post-slug.php напрямую), но это сопоставляется с /post-slug.php внутренне. Я переписал свой ответ. (Нужно ли вам обрабатывать ситуацию, если пользователь должен запросить /post-slug.php напрямую? Например, были ли эти .php URL-адреса проиндексированы поисковыми системами или на них ссылаются третьи лица?)

MrWhite 06.06.2019 23:33

Привет! Извините за мой поздний ответ! Мне удалось заставить его работать с вашим последним ответом, большое спасибо!

Alex1337 20.06.2019 14:53

Другие вопросы по теме