mod_rewrite - как перенаправить опечатку 'симпатичного' URL - PullRequest
2 голосов
/ 19 ноября 2011

У меня есть сайт, написанный на php, который создает «красивые» URL для каждого элемента (на страницах категории и поиска), например,

mysite.com/category/slug-for-item-one/1
mysite.com/category/slug-for-item-two/2

/ category / и / slug / зависит от числового идентификатора элемента

У меня есть mod_rewrite, обслуживающий фактический контент с URL-адресов:

mysite.com/view-item.php?id=1
mysite.com/view-item.php?id=2

Содержимое для каждого элемента извлекается с использованием только идентификатора элемента.

Вот мой htaccess:

RewriteEngine on
RewriteRule ^([^/\.]+)/?$ view-item.php?id=$1 [L]
RewriteRule ^([^/\.]+)/([^/\.]+)/?$ view-item.php?pid=$2 [L]
RewriteRule ^([^/\.]+)/([^/\.]+)/([^/\.]+)/?$ view-item.php?id=$3 [L]

Пока все нормально, но, если кто-то попадает на URL-адрес,

mysite.com/1
mysite.com/catey/slug-for-item-one/1 

или

mysite.com/category/slug-item-one/1

контент все еще обслуживается, но как я могу автоматически сбросить или перенаправить на каноническую версию URL, чтобы:

mysite.com/category/slug-for-item-one/1

Я искал в SO и Google много ответов, но не повезло. Я использовал mod_rewrite только для простых перенаправлений, таких как без www. чтобы с www. и мое понимание является предварительным, поэтому я изо всех сил пытаюсь понять, как действовать в данный момент.

Кто-нибудь может указать мне правильное направление?

Спасибо всем за помощь. Очень признателен. Я работаю над реализацией ответа Джона Линя, так как я более знаком с использованием баз данных php / mysql и понимаю, как и почему он должен работать. Я собираюсь сделать это к пятнице и обновлю эту страницу, когда закончу. Большое спасибо, Карл.

* ОБНОВЛЕНИЕ * Я реализовал ответ Джона Линя и теперь мои «красивые» URL-адреса, когда опечатки теперь перенаправляются на правильный или «канонический» URL-адрес, как в SO. Спасибо Джон и всем, кто внес свой вклад!

Ответы [ 3 ]

2 голосов
/ 19 ноября 2011

Я думаю, вам понадобятся два набора правил переписывания, чтобы выполнить это.

Первый набор правил будет использоваться для отправки клиенту перенаправлений 301, чтобы убедиться, что они ссылаются на канонические URL-адреса:

RewriteRule ^/1    /category/slug-for-item-one/1 [R=301,L]

Затем второй набор правил, использующих сквозные переходы [PT] для обслуживания контента:

RewriteRule ^([^/\.]+)/([^/\.]+)/([^/\.]+)/?$ view-item.php?id=$3 [PT,L]

Или что-то в этом роде ...

1 голос
/ 19 ноября 2011

Easy as pie:

RewriteCond %{REQUEST_URI} ^([^/\.]+)/([^/\.]+)/([^/\.]+)/$
RewriteCond %1 !category
RewriteRule ^([^/\.]+)/([^/\.]+)/([^/\.]+)/$ $1/category/$3/

Это означает: если запрос выглядит как category/slug-for-item-two/2 и , первое совпадение не является словом category (что бы это ни было), затем принудительно перенаправьте на category/slug-for-item-two/2

Скажите, пожалуйста, работает ли оно


Обновите (после вашего комментария):

Вот чтодолжно работать:

Создать 2 файла карты (см. mod_rewrite.html # rewritemap , чтобы узнать, как это сделать).

Создайте файл карты, куда вы поместите все нужные категории:

RewriteMap mapcategories \
  dbm:/web/htdocs/yoursite/rewriterules/categories.map

В файле карты создайте простые записи, например:

shirts 1
hats 2
condoms 3
vegetables 4
mother-in-laws 5
...

Теперь создайте другой файл с обратным:

RewriteMap mapcategoriesreverse \
  dbm:/web/htdocs/yoursite/rewriterules/categoriesreverse.map

В файле карты создайте простые записикак:

1 shirts
2 hats
3 condoms
4 vegetables
5 mother-in-laws
...

Затем перейдем к сложной части:

RewriteCond %{REQUEST_URI} ^([^/\.]+)/([^/\.]+)/([^/\.]+)/$
# The following rule will try to search into the categories map file
# and if not found, assign CATEGORY to "notfound"
RewriteRule ^([^/\.]+)/([^/\.]+)/([^/\.]+)/$ \
    - [QSA,E=CATEGORY:${mapcategories:%1|notfound}]

# if the CATEGORY is not empty and is not found:
RewriteCond %{ENV:CATEGORY} notfound
# do a reverse map to get the *real* category:
RewriteRule ^([^/\.]+)/([^/\.]+)/([^/\.]+)/$ \
    - [QSA,E=CATEGORYREVERSE:${mapcategoriesreverse:%1|notfound}]

# if the CATEGORYREVERSE is not empty and is not found:
RewriteCond %{ENV:CATEGORYREVERSE} notfound
# this should never happen => 404:
RewriteRule . - [R=404,L]

# If reach here = if the CATEGORYREVERSE is not empty
# this means it has properly been found:
RewriteCond %{ENV:CATEGORYREVERSE} !^$
# Inject the right category:
RewriteRule ^([^/\.]+)/([^/\.]+)/([^/\.]+)/$  \
    %{ENV:CATEGORYREVERSE}/$2/$3/ [QSA]

Таким образом, все динамично, но (намного) длиннее и (немного) сложнее.

Оливье

0 голосов
/ 19 ноября 2011

Это, вероятно, то, что вы хотите реализовать в view-item.php вместо того, чтобы пытаться использовать mod_rewrite. Когда вы генерируете ссылки внутри своего контента, вы можете использовать идентификаторы для поиска категорий и слагов. Это будет то, как вы обычно генерируете одну из симпатичных SEO-дружественных ссылок.

Сначала нужно передать категорию и слаг в запрос. Что-то вроде:

RewriteEngine on
RewriteRule ^([^/\.]+)/?$ view-item.php?id=$1 [L]
RewriteRule ^([^/\.]+)/([^/\.]+)/?$ view-item.php?pid=$2&cat=$1 [L]
RewriteRule ^([^/\.]+)/([^/\.]+)/([^/\.]+)/?$ view-item.php?id=$3&cat=$1&slug=$2 [L]

В верхней части вашего view-item.php просто проверьте, существуют ли параметры cat и slug, сравните их с фактической категорией и задайте значение, когда вы выполняете поиск для id. Если один из них не совпадает (или отсутствует, если хотите), то перенаправьте браузер на правильную ссылку с правильной категорией и добавьте команду, используя функцию header():

header('HTTP/1.1 301 Moved Permanently');
header("Location: " . $correct_url);
exit();

После того, как они перенаправлены, процесс повторяется, но на этот раз view-item.php видит правильную категорию и фрагмент, чтобы страница обслуживалась как обычно.

...