Добавить завершающий слэш через .htaccess
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*[^/])$ $1/ [L,R=301]
Удалить завершающий слэш через .htaccess
RewriteBase /
RewriteCond %{HTTP_HOST} (.*)
RewriteCond %{REQUEST_URI} /$ [NC]
RewriteRule ^(.*)(/)$ $1 [L,R=301]
Вышеприведенные решения работают только для простых случаев (у меня, например). Если у вас в .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 лучше не маяться и не ставить завершающий слеш (а, наоборот, убирать). Из-за того, что в ней используются всякие адреса с GET-параметрами.