• PHP
  • htaccess

Как сделать ссылку без расширения php?

Всем Доброго времени суток и с Наступающим Новым Годом!

Как сделать путь без указания расширения? Например есть путь:
mysite.ru/keys/book_275.php
Необходимо:
mysite.ru/keys/book_275
Или даже как сделано на этом же сайте https://itchief.ru/questions.

Сайт самописный, на локальном сервере.

Нашел 2 варианта:

1 способ:

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

Но в этом случае на всех старницах сайта нужно удалять расширение файлов php. Да и сам документ nav.php который подключаю ко всем страницам через include, я так понимаю нужно будет переименовывать?

2 способ работает, но я сомневаюсь в адекватности кода

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^.*$ $0.php [L,QSA]
RewriteCond %{THE_REQUEST} ([^\s]*)\.php(\?[^\s]*)?
RewriteRule (.*) %1 [R=301,L]
RewriteEngine On
RewriteRule ^index.php$ / [QSA,R]

Есть кто шарит в этом и может помочь, какой вариант лучше или вообще как это реализвать правильно?)

Спасибо!

Комментарии: 11

Антон
Антон
Александр, приветствую! Спасибо! Но как то странно это решение работает… Одни старницы норм открывает без расширения, а другие страницы в этой же папке выдает ошибку… Хотя страницы считай идентичны…

Объект не найден!

Запрашиваемый ресурс не найден. Ссылка на странице неверна или устарела. Пожалуйста, сообщите автору этой страницы об ошибке.

Если Вы считаете, что это ошибка сервера, пожалуйста, сообщите об этом веб-мастеру.
Error 404
share
Apache
Александр Мальцев
Александр Мальцев
Пожалуйста! Точное решение сложновато подсказать, т.к. оно будет зависеть от того, как вы организовали этот самописный сайт, а также от среды, в которой он будет работать.
Если вам подходит решение №2, то используйте его.

В движках (CMS) это обычно выполняется в php коде, а не в «.htaccess». Т.к. в php можно написать любую очень гибкую логику, чем в «.htaccess».
Для этого в «.htaccess» добавляется следующая конструкция, которая в данном случае будет перенаправлять все запросы в «index.php» (точку входа):
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
Антон
Антон
Правильно я понимаю, что нужно добавить только этот код?
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
и не нужен RewriteEngine On?

Либо добавить этот фрагмент к уже добавленному коду?

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

# Rewrite /foo/bar to /foo/bar.php
RewriteRule ^([^.?]+)$ %{REQUEST_URI}.php [L]

# Return 404 if original request is /foo/bar.php
RewriteCond %{THE_REQUEST} "^[^ ]* .*?\.php[? ].*$"
RewriteRule .* - [L,R=404]

# NOTE! FOR APACHE ON WINDOWS: Add [NC] to RewriteCond like this:
# RewriteCond %{THE_REQUEST} "^[^ ]* .*?\.php[? ].*$" [NC]
Все равно попробывал 2 варианта, добави все «.htaccess» на обих ссылка в адресной строке меняется, но почему то всегда отображается только index.php…
Сайт самый обычный без каких либо внешних подключений, использоваться будет просто загрузкой на хостинг например «beget и тд». Пути к файлам самые обычные через например: /img/img_1.png
единственное подключние есть через php include когда ко все файлам подключаю nav.php.

P.S. Прощу прощения за такой детальный распрос, но недопонял этот момент.
Александр Мальцев
Александр Мальцев
Да, «RewriteEngine On» нужно добавить. Но этот код вам нет смысла добавлять:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
Я его написал для примера, как это реализовано в CMS. Если это сделаете, то тогда роутинг вам нужно будет реализовывать в PHP.

Если у вас там всё просто, то этот вариант должен работать:
RewriteEngine on
RewriteRule ^([^.?]+)$ %{REQUEST_URI}.php [L]
RewriteCond %{THE_REQUEST} "^[^ ]* .*?\.php[? ].*$"
RewriteRule .* - [L,R=404]
# RewriteCond %{THE_REQUEST} "^[^ ]* .*?\.php[? ].*$" [NC]
В Windows для Apache раскомментируйте последнюю строчку. Но, если разрабатываете, то лучше в среде более близкой к тому, что у вас будет на хостинге.

Попробуйте добавить ещё в начало вашего «.htaccess»:
Options -MultiViews
Антон
Антон
Понятно! Как вы и сказали попробовал этот вариант и с этой строчкой «Options -MultiViews» и без.
Но история почему то повторяется Одни старницы норм открывает без расширения, а другие страницы в этой же папке выдает ошибку… Хотя страницы считай идентичны…

Ладно бог с ним! Как вы и сказали буду использовать 2 свой вариант. Просто в этом коде я вообще ни строчки не понимаю, поэтому и хотел уточнить, нет ли там каких либо скрытых запросов или ненужных действий которые приведут к лишней загрузке или попадалову...)
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^.*$ $0.php [L,QSA]
RewriteCond %{THE_REQUEST} ([^\s]*)\.php(\?[^\s]*)?
RewriteRule (.*) %1 [R=301,L]
RewriteEngine On
RewriteRule ^index.php$ / [QSA,R]
P.S. А вообще интересно обязательно ли скрывать расширение или нет? Или все это делается для красоты?
Антон
Антон
Александр, приветствую! Я догадываюсь уже замучил вас))) Да что там говорить и себя замучил уже!)
Все таки и мой 2 вариант не подходит поскольку ссылки начинают дублироваться открываясь 2 адресам:
Например www.site.ru/book/key_1.php и www.site.ru/book/key_1. Начал пробовать все подрят, как сделать так чтобы переходило только по 1 адресу www.site.ru/book/key_1. В итоге вернулся в вашему же коду который вы мне подсказали ниже, поэтому могли бы вы мне подсказать пару моментов?
RewriteEngine on
RewriteRule ^([^.?]+)$ %{REQUEST_URI}.php [L]
RewriteCond %{THE_REQUEST} "^[^ ]* .*?\.php[? ].*$"
RewriteRule .* - [L,R=404]
# RewriteCond %{THE_REQUEST} "^[^ ]* .*?\.php[? ].*$" [NC]
1 Вопрос -> Насколько я понимаю прописывая этот код нужно все ссылки в коде поменять и убрать php (c /book/key_1.php на /book/key_1)? По крайне мере у меня так сработало. И потом когда я переду по другому адресу с расширением php (/book/key_1.php) выдаст 404 not found. Что в принципе и правильно насколько я понимаю? Я этого вообще например не знал, так ли это?
Непонятно как быть с подключаемыми файломи:
<?php include($_SERVER['DOCUMENT_ROOT']. '/nav.php');?> У них что тоже расширение убирать? Тогда они перестают запускаться…

2 Вопрос -> Как изменить этот код, чтобы когда указывается неправильный путь открывалась не серверная страница 404 not found а своя? Как прописать ErrorDocument /404.php чтобы это все не ломалось?

3 Вопрос -> Как опять же изменить этот код чтобы адрес был без index т.е есть логотип на сайте нажимая на который, ты переходишь на главную страницу, так вот, я изначально писал путь: /index.php, но щас начал просто указывать "/" (в чем сомневаюсь нужно ли так делать?) И в этом случае действительно с адресной строки убираетсяindex а код выше убирает php. Но все равно если я указываю www.site.ru/index он открывается, а нужно только чтобы переходило по 1 адресу www.site.ru.

Благодрю если осилили этот текст до конца, и за помощь! ;)
Александр Мальцев
Александр Мальцев
В этом случае вам нужно просто разобрать, что делает каждая строчка.
Например:
# включаем механизм mod_rewrite
RewriteEngine On
# задаём 3 дополнительных условия для правила RewriteRule, находящего сразу после этих директив:
### 1. если запрос не является файлом
RewriteCond %{REQUEST_FILENAME} !-f
### 2. если запрос не является файлом
RewriteCond %{REQUEST_FILENAME} !-d
### 3. если запрос при добавлении к нему .php является файлом
RewriteCond %{REQUEST_FILENAME}.php -f
# если все 3 дополнительных условия выполнены и строка соответствует регулярному выражению (^.*$), то преобразовываем строку в новую посредством добавления к ней .php и отменяем следующие проверки (флаг L)
RewriteRule ^.*$ $0.php [L,QSA]
RewriteCond %{THE_REQUEST} ([^\s]*)\.php(\?[^\s]*)?
RewriteRule (.*) %1 [R=301,L]
RewriteEngine On
RewriteRule ^index.php$ / [QSA,R]
К остальным строчкам, чтобы было понятно, тоже необходимо добавить комментарии. После этого будет полная картина того, что этот код делает.

Скрывать расширение страницы — это хорошая практика, т.к. не будет лишней информации в URL. Да, и URL от этого будет выглядеть более красиво.
Александр Мальцев
Александр Мальцев
Привет!
Да, доступ к конкретной странице должен всегда осуществляться по одному адресу. С точки зрения поисковой оптимизации очень плохо, если один и тот же контент будет доступен по разным URL.
Т.е., например, страницу «/book/key_1» необходимо открывать только так и никак иначе:
www.site.ru/book/key_1
1. Ссылки в HTML-коде, который вы будете передавать на клиент должны быть на эту страницу только в таком виде:
/book/key_1
Обратиться к ней через «/book/key_1.php» конечно нужно запретить. У вас должна выдаваться в этом случае «ошибка 404» (такой страницы не существует). Иначе для SEO это будет очень плохо, т.к. одинаковый контент у вас будет присутствовать по разным URL.
В PHP коде ничего убирать не надо, в данном случае эти правила (в «.htaccess») здесь не причём. Вы просто включаете этот файл «nav.php» в текущий файл:
<?php include($_SERVER['DOCUMENT_ROOT']. '/nav.php');?>
2. Сделать страницу 404 со своим контентом и указать путь к ней в «.htaccess»:
ErrorDocument 404 /404.php
3. Один контент должен всегда находиться по одному URL. Это же касается и главной страницы. Она должна быть доступна только по «/». В случае, если мы указываем «www.site.ru/index» мы должны сделать редирект на главную или 404 (тут уже на своё усмотрение).
Антон
Антон
Александр, Огромное Спасибо Вам за полезную информацию, и что вы всегда на связи и помогаете! Теперь хоть есть примерное понимание куда копать.
Вроде получилось все сделать и даже «о чудо, он работает», но все равно можете взглянуть на адекватность кода и подправить в паре моментов?
Вот первоначальный код, он грубо говоря удаляет отсекает все что оканчивается на php.
RewriteEngine on
RewriteRule ^([^.?]+)$ %{REQUEST_URI}.php [L]
RewriteCond %{THE_REQUEST} "^[^ ]* .*?\.php[? ].*$"
RewriteRule .* - [L,R=404]
# RewriteCond %{THE_REQUEST} "^[^ ]* .*?\.php[? ].*$" [NC]
К нему как вы и сказали добавил редирект с www.site.ru/index на 404 not found.
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /index\ HTTP/
RewriteRule .* - [L,R=404]
И добавил ErrorDocument 404 /err404.php В итоге получилась общая конструкция:
ErrorDocument 404 /err404.php
RewriteEngine on
RewriteRule ^([^.?]+)$ %{REQUEST_URI}.php [L]
RewriteCond %{THE_REQUEST} "^[^ ]* .*?\.php[? ].*$"
RewriteRule .* - [L,R=404]
# RewriteCond %{THE_REQUEST} "^[^ ]* .*?\.php[? ].*$" [NC]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /index\ HTTP/
RewriteRule .* - [L,R=404]
И вот тут можете подсказать? Адекватно ли сделан редирект, просто никогда его не далал и написал методом поиска чего то более адекватного в инете.
И почему то для этих правил не работает ErrorDocument 404 /err404.php ( т.е когда я в адрессной строке пишу www.site.ru/index или www.site.ru/book.php. У меня выходит стандартный 404, а не мой подключенный… Но когда я вбиваю в адрессную строку random adress: www.site.ru/random, то уже выходит моя страница с 404!!!
Следовательно причина я так думаю в RewriteRule .* — [L,R=404], но как их подправить не совсем понимаю. Проще говоря почему то мое подключение 404 игнорится при наличии php, index в адресной строке.
Еще раз благодарю!)
Антон
Антон
Ясно! Спасибо!
Александр Мальцев
Александр Мальцев
Привет! На php.net для этого случая приведено такое решение:
RewriteEngine on

# Rewrite /foo/bar to /foo/bar.php
RewriteRule ^([^.?]+)$ %{REQUEST_URI}.php [L]

# Return 404 if original request is /foo/bar.php
RewriteCond %{THE_REQUEST} "^[^ ]* .*?\.php[? ].*$"
RewriteRule .* - [L,R=404]

# NOTE! FOR APACHE ON WINDOWS: Add [NC] to RewriteCond like this:
# RewriteCond %{THE_REQUEST} "^[^ ]* .*?\.php[? ].*$" [NC]