Проблема из-за слэша в конце URL
Неприятность относится к области SEO (поисковой оптимизации), а именно: к дублям страниц. В отличие от случая с дублированием по www, у этого варианта больше шансов остаться незамеченным. Часто внутренние подсистемы обработки запросов самописных (а то и публично известных) фреймворков и CMS просто берут в расчет только то, что между слэшами.
Далеко за примером ходить не надо, возьмем тот же Zend Framework. Внутри этого фреймворка реализована своя система маршрутизации, в зависимости от URL-адреса, по которому обращаются к сайту. То есть, изначально не требуется воротить сложные конструкции регулярок в htaccess и довести до белого каления с десяток форумов по веб-программированию. Все обращения к сайту перенаправляются на главный скрипт index.php, внутри которого подключаются уже классы и начинает работать программная маршрутизация, распарсивая URL на части и определяя тем самым, какие классы и методы в них надо вызывать.
Например, по-умолчанию (без подробностей, объясню попроще), адрес вида http://site.ru/user/register/form/ означает, что системе следует найти модуль «user», внутри которого содержится класс со специфическим именем «RegisterController» и у этого класса вызвать метод «form()».
Но беда в том, что для определения дальнейших действий в ход идут исключительно составные части адреса, без слэшей: user, register, form. И даже если мы уберем слэш в конце URL, то получим те же самые параметры, и результат работы сайта будет тот же самый. А адреса http://site.ru/user/register/form/ и http://site.ru/user/register/form — равноценными, по которым находятся дубли страниц.
Знакомые с PHP могут попробовать самостоятельно написать простой «интерпретатор» для URL. В результате чего увидят, что отслеживать слэш в конце URL не имеет смысла. Потому создатели CMS (редко) и фреймворков (практически всегда) отдают этот вопрос на решение разработчикам и вебмастерам конкретных сайтов.
Большинство из нас именно является, самокритично выражаясь, пользователями готовых решений разной степени квалификации. Поэтому на нас ложится груз ответственности предусмотреть эту ситуацию и предохраниться от дубликатов.
Добавить завершающий слэш через .htaccess
RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_URI} !(.*)/$ RewriteRule ^(.*[^/])$ $1/ [L,R=301]
Удалить завершающий слэш через .htaccess
<code>RewriteBase / RewriteCond %{HTTP_HOST} (.*) RewriteCond %{REQUEST_URI} /$ [NC] RewriteRule ^(.*)(/)$ $1 [L,R=301]</code>
Вышеприведенные решения работают только для простых случаев (у меня, например). Если у вас в .htaccess уже полно всяких RewriteRule, то могут возникнуть конфликты между правилами. Тогда следует позвать специалиста и разбираться отдельно в каждом конкретном случае.
Удалить слеш программно (PHP)
// Получаем URI для проверки $uri = preg_replace("/\?.*/i",'', $_SERVER['REQUEST_URI']); if (strlen($uri)>1) {// если не главная страница... if (rtrim($uri,'/')!=$uri) { header("HTTP/1.1 301 Moved Permanently"); header('Location: http://'.$_SERVER['SERVER_NAME'].str_replace($uri, rtrim($uri,'/'), $_SERVER['REQUEST_URI'])); exit(); } }
Для Joomla надо учесть наличие админ-интерфейса по адресу /administrator/ — там лучше не редиректить, а то циклическое перенаправление получается (код вставлять в начало index.php):
$uri = preg_replace("/\?.*/i",'', $_SERVER['REQUEST_URI']); if ((!strpos($uri, 'administrator')) && (strlen($uri)>1)) { if (rtrim($uri,'/')!=$uri) { header("HTTP/1.1 301 Moved Permanently"); header('Location: http://'.$_SERVER['SERVER_NAME'].str_replace($uri, rtrim($uri,'/'), $_SERVER['REQUEST_URI'])); exit(); } }
Добавить слеш программно (PHP)
// Получаем URI для проверки $uri = preg_replace("/\?.*/i",'', $_SERVER['REQUEST_URI']); if (strlen($uri)>1) {// если не главная страница... if (rtrim($uri,'/')."/"!=$uri) { header("HTTP/1.1 301 Moved Permanently"); header('Location: http://'.$_SERVER['SERVER_NAME'].str_replace($uri, $uri.'/', $_SERVER['REQUEST_URI'])); exit(); } }
Для Joomla лучше не маяться и не ставить завершающий слеш (а, наоборот, убирать). Из-за того, что