Назад | Перейти на главную страницу

Mod_rewrite заменяет подчеркивание дефисом (или дефисом) в Opencart

Я перевожу сайт электронной коммерции в новую корзину. По какой-то причине на старом сайте для категорий использовались тире, а для продуктов - знаки подчеркивания.

Таким образом, полный URL-адрес продукта выглядит так:

http://www.example.com/Engineering-Common-Bricks/65mm_Class_B__Solid_Engineering_Brick__Price_Each

В новой корзине для всего используются тире, поэтому мне нужно переписать входящие URL-адреса, такие как приведенные выше, на следующие:

http://www.example.com/Engineering-Common-Bricks/65mm-Class-B--Solid-Engineering-Brick--Price-Each

Я знаю, что есть много материалов о замене подчеркивания на тире, но, похоже, ни один из них не работает для меня.

Я использую Opencart, который поставляется с существующим набором правил перезаписи, поэтому, возможно, они мешают новым правилам, которые я пытаюсь добавить.

Существующий .htaccess как следует:

Options +FollowSymlinks

# Prevent Directoy listing 
Options -Indexes

# Prevent Direct Access to files
<FilesMatch "\.(tpl|ini|log)">
 Order deny,allow
 Deny from all
</FilesMatch>

# SEO URL Settings
RewriteEngine On
# If your opencart installation does not run on the main web folder make sure you folder it does run in ie. / becomes /shop/ 

RewriteBase /
RewriteRule ^sitemap.xml$ index.php?route=feed/google_sitemap [L]
RewriteRule ^googlebase.xml$ index.php?route=feed/google_base [L]
RewriteRule ^download/(.*) /index.php?route=error/not_found [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !.*\.(ico|gif|jpg|jpeg|png|js|css)
RewriteRule ^([^?]*) index.php?_route_=$1 [L,QSA]

Любая помощь или направление будут с благодарностью приняты.


Обновление .htaccess согласно ответу Эсы на следующее:

Options +FollowSymlinks
Options -Indexes

<FilesMatch "\.(tpl|ini|log)">
 Order deny,allow
 Deny from all
</FilesMatch>

RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^_]*)_([^_]*_.*) $1-$2 [N]
RewriteRule ^([^_]*)_([^_]*)$ /$1-$2 [L,R=301]

RewriteBase /
RewriteRule ^sitemap.xml$ index.php?route=feed/google_sitemap [L]
RewriteRule ^googlebase.xml$ index.php?route=feed/google_base [L]
RewriteRule ^download/(.*) /index.php?route=error/not_found [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !.*\.(ico|gif|jpg|jpeg|png|js|css)
RewriteRule ^([^?]*) index.php?_route_=$1 [L,QSA]

Отлично работает для:

http://example.com/this_is_a_category

Но приводит к сбою Apache:

http://example.com/this_is_a_category/this_is_a_product

Поскольку RewriteRules предназначены для совпадений регулярных выражений, а не замен, первая строка в

RewriteRule ^([^_]*)_([^_]*_.*) $1-$2 [N]
RewriteRule ^([^_]*)_([^_]*)$ /$1-$2 [L,R=301]

не повторяется. Поэтому вам понадобится одна строка для каждого количества подчеркиваний, например

RewriteRule ^(.*)_(.*)_(.*)_(.*)_(.*)_(.*)_(.*)$ /$1-$2-$3-$4-$5-$6-$7 [R=301,L]
RewriteRule ^(.*)_(.*)_(.*)_(.*)_(.*)_(.*)$ /$1-$2-$3-$4-$5-$6 [R=301,L]
RewriteRule ^(.*)_(.*)_(.*)_(.*)_(.*)$ /$1-$2-$3-$4-$5 [R=301,L]
RewriteRule ^(.*)_(.*)_(.*)_(.*)$ /$1-$2-$3-$4 [R=301,L]
RewriteRule ^(.*)_(.*)_(.*)$ /$1-$2-$3 [R=301,L]
RewriteRule ^(.*)_(.*)$ /$1-$2 [R=301,L]

заменяет 1–5 знаков подчеркивания, в результате

/Engineering_Common_Bricks/65mm_Class_B-Solid-Engineering-Brick-Price-Each

поэтому для 9 замен вам понадобится еще несколько строк вверху. Шаблон будет таким же, но более длинные выражения должны стать первыми.

Однако при этом все символы подчеркивания заменяются дефисами (и выполняется перенаправление после последнего), поэтому у вас не должно быть имен файлов, содержащих символы подчеркивания. Вы также можете предотвратить это, добавив директиву RewriteCond ПЕРЕД этими правилами:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^_]*)_([^_]*_.*) $1-$2 [N]
RewriteRule ^([^_]*)_([^_]*)$ /$1-$2 [L,R=301]

Прекрасно работает для:

http://example.com/this_is_a_category

Но приводит к сбою Apache:

http://example.com/this_is_a_category/this_is_a_product

Чтобы решить эту проблему, вам просто нужно добавить DPI (Отменить информацию о пути) к первому RewriteRule директива:

RewriteRule ^([^_]*)_([^_]*_.*) $1-$2 [N,DPI]
RewriteRule ^([^_]*)_([^_]*)$ /$1-$2 [L,R=301]

"Сбой Apache" вызван бесконечный переписать цикл. В N Флаг вызывает цикл набора правил (что требуется в этом сценарии для замены всей полосы одним из подчеркиваний), однако информация о пути из исходного запроса добавляется к перезаписанному URL-адресу на каждой итерации (по замыслу).

В первом примере с одним сегментом пути нет дополнительной информации о пути, поэтому ничего не добавляется. Однако второй пример содержит дополнительную информацию о пути, а именно /this_is_a_product (все, что находится после первого сегмента пути, который не соответствует пути физической файловой системы), который сам содержит символы подчеркивания. Это проблема. Каждая итерация цикла заменяет только одно подчеркивание, но каждая итерация цикла также добавляет еще 3 (в этом примере)! Таким образом, он никогда не сможет выполнить задачу по замене всех (за исключением одного) подчеркивания!

Если вы включите перезапись журнала, журнал ошибок будет сообщать что-то вроде:

/this_is_a_category/this_is_a_product
/this-is_a_category/this_is_a_product/this_is_a_product
/this-is-a_category/this_is_a_product/this_is_a_product/this_is_a_product
/this-is-a-category/this_is_a_product/this_is_a_product/this_is_a_product/this_is_a_product
/this-is-a-category/this-is_a_product/this_is_a_product/this_is_a_product/this_is_a_product/this_is_a_product
:

Как видите, это очень быстро выходит из-под контроля. По умолчанию он останавливается после 32 000 итераций (!), Но, вероятно, ваш сервер до этого времени исчерпает ресурсы; отсюда и авария. В Apache 2.4.8+ вы можете ограничить количество итераций, например. N=10 - хотя это не решит вашу проблему, это предотвратит сбой вашего сервера!

AFAIK, DPI flag (Apache 2.2.12+) был специально создан для решения этой проблемы. Он удаляет исходную информацию о пути из перезаписанного URL-адреса, поэтому он не добавляется каждый раз заново, что предотвращает бесконечный цикл перезаписи.

Ссылка: