Меняем URL по шаблону (микрохак)

+32
3.39K
Доброго времени суток, уважаемое сообщество!
Раз уж пошла такая байда, выложу инструкцию, как поменять URL по шаблону. То что нужно было, проверил. Вроде всё работает. Всё проверить один не сумею. Поэтому я выложу, а вы сами тестируйте, эксперементируйте на локалхосте. К тому же у сайтостроителей фантазия намного развитей, чему у меня smile. Потребности по замене url большие…

Для начала давайте уясним, не всё, что вы хотите можно решить… Любая ошибка приведет к странице 404. Поэтому, прежде чем проверять на рабочем сайте, проверяйте на локалхосте.

Итак, поехали. Для начала о микрохаке. Открываем файл ядра /core/cms.php. Находим метод detectURI(). В методе уже насколько я понял заложена замена по шаблону. Может и ошибаюсь. В общем, не смог я понять одну конструкцию. Что-то для меня новое. И погуглил, и думал. Так и не додумался. Это вот этот кусок кода
  1. foreach($matches as $key=>$value){
  2. if (!$key) { continue; }
  3. if (strstr($rule['target'], '{'.$key.'}')){
  4. $rule['target'] = str_replace('{'.$key.'}', $value, $rule['target']);
  5. }
  6. }
Вроде он не работает. Буду благодарен, если кто объяснит.
Я пошел другим путем ) Итак, начинаем изменения. Находим строку примерно 1563
  1. foreach($rules as $rule_id=>$rule) {
меняем на
  1. foreach($rules as $rule_id=>&$rule) {
Чуть ниже, после строки 1567
  1. if (preg_match($rule['source'], $uri, $matches)){
вставляем
  1. $rule['target'] = preg_replace($rule['source'], $rule['target'], $uri);
Вот и всё. Микрохак завершен. После данных действий вроде бы всё работает.

Далее, перейдем к самим шаблонам. Нужно создать файл custom_rewrite.php в корне сайта. А ещё лучше взять его из архива разработки и положить в корень сайта. Если устанавливали сам компонент и плагин, тогда этот файл у вас уже есть. Просто откройте в редакторе.

Далее приведу пару примеров, как строим правило в этом файле. Всё идет подобно файлу url_rewrite.php. Открываем и смотрим. Правило выглядит так:
  1.  
  2. $rules[] = array(
  3. 'source' => '/^users(.*?)$/is',
  4. 'target' => 'http://i19.ru/ludi$1',
  5. 'action' => 'redirect-301'
  6. );
  7.  
  8. $rules[] = array(
  9. 'source' => '/^ludi(.*?)$/is',
  10. 'target' => 'users$1',
  11. 'action' => 'rewrite'
  12. );
  13.  
Это мы меняем название компонента users на ludi. Много раз обсуждали, как это сделать. Вот ещё один метод.
Первый блок делаем редирект-301 на новый урл. Второй блок для нового урл делаем реврайт(подменяем на старый).
Как это работает, объяснять смысла нет. Кому нужно, тот поймет. Кто не понимает, ищем "регулярные выражения в php" и изучаем. Процесс будет нелегкий. Возможно даже лучше попросить того, кто знает. По секрету скажу, что даже кодеры делятся на тех, кто знает, и кто не знает. Я в числе тех, кто немного слышал про регулярки )))

Второй пример. Меняем "/stati/какая_то_категория/какая_то_статья" на "/stati/какая_то_категория-какая_то_статья". Кому-то нужно было так.
  1.  
  2. $rules[] = array(
  3. 'source' => '/^stati\/(.*?)\/(.*?)$/is',
  4. 'target' => 'http://i19.ru/stati/$1-$2',
  5. 'action' => 'redirect-301'
  6. );
  7.  
  8. $rules[] = array(
  9. 'source' => '/^stati\/(.*?)-(.*?)$/is',
  10. 'target' => 'stati/$1/$2',
  11. 'action' => 'rewrite'
  12. );
  13.  
Будет меняться. Но надо будет иметь ввиду, что если кто-то создаст в категории /stati/ какую-то статью, то для этой страницы будет 404 ответ сервера. Вот так вот. Такая это тонкая материя.

В общем, я дал пример. А дальше уже сами. С регулярками у меня не всё гуд, да и времени в данный момент недостаточно, чтобы совершенствоваться. Наверно, лучше будет так. Кому что нужно(подробно что и на что менять) пишем в комментариях. Кто знает/может/есть желание анализируют и пишут правило под эту замену.

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

Ах, да! В примерах http:// i19.ru нужно заменить на ваш сайт по подобию.

Приятного пользования!
+5
Марат Марат 12 лет назад #
А я пошел паковать чумаданы )))
+2
Positive Positive 12 лет назад #
Мы протестируем, а тебе хорошего отдыха!!!!
+2
Bubble Gumoff Bubble Gumoff 12 лет назад #
Марат, спасибо!!! Отдохни хорошенько, буду ждать твоего возвращения, так как вопросы появятся
+1
Александр Александр 12 лет назад #
Большое спасибо, отличного тебе отпуска!
0
Gino Fernandes Gino Fernandes 12 лет назад #
Приятного отдыха! Возвращайся скорее с новыми силами и свежей головой
0
Роман Роман 12 лет назад #
Сам отдыхай, но про инстант не забывай!!! :)) Удачно отдохнуть :))
Олег Васильевич я Олег Васильевич я 12 лет назад #
Комментарий удален
+1
Марат Марат 12 лет назад #
Давайте в личку, что именно не работает. Желательно поподробнее.
0
googlebot googlebot 12 лет назад #
Желаю хорошо отдохнуть:) помнится на 1.8 баловался с custom_rewrite.php и вроде все работало и без хаков...
+1
Марат Марат 12 лет назад #
С custom_rewrite.php всё нормально. Работает. Для простых правил. Это когда просто один ури менять на другой по точному соотвествию, что и сделано в предыдущем моем посте в блоге.
Проблемы возникают тогда, когда хотим менять ури по шаблону. Например, все ури /users/* на /ludi/* одним правилом. Ну или вообще что-то наподобие делать. Теоретически должно работать. В правилах используются регулярные выражения. В регулярках можно использовать карманы в функции замены. Но если написать в $target выражение $1 то совпадение с первого кармана не подставляется за место $1. А без этого замену по шаблону никак не сделать. Микрохак нужен только для этого.
Олег Васильевич я Олег Васильевич я 12 лет назад #
Комментарий удален
Олег Васильевич я Олег Васильевич я 12 лет назад #
Комментарий удален
+1
Марат Марат 12 лет назад #
Можно, без проблем. Но у вас в данном случае простое сопвадение. Один ури меняем на другой. Тут шаблон не нужен. Установите компонент seo-pages и даже сами сделаете это без проблем. Плюс ещё(если нужно) добавите кейворды, дэскрипшон и поменяете тайтл.
+1
Марат Марат 12 лет назад #
Компонент как раз предназначен для того, чтобы вручную не редактировать файл custom_rewrite.php
-1
letsgo letsgo 12 лет назад #
Есть возможность изменить site.ru/stati/statia на site.ru/statia ?
Олег Васильевич я Олег Васильевич я 12 лет назад #
Комментарий удален
-1
letsgo letsgo 12 лет назад #
site.ru/stati-statia делали вариант для для одного из компонентов. Результат весьма эффективен. Уровень урла важен. Но хаки есть хаки. Представленное делает /stati-statia массово на весь компонент без изменения файлов компонента?
Олег Васильевич я Олег Васильевич я 12 лет назад #
Комментарий удален
-1
letsgo letsgo 12 лет назад #
Да, это серьезный момент. Не хочется ставить кучу хаков, которые надо потом отслеживать, когда много сайтов это затягивается и нудный процесс. По сути в этом плане отлично реализован выбор уровня урла у длехи, там либо id-nazvanie либо razdel/nazvanie либо через дату. Конечно к этому желательно, чтобы пришел и Инстант в официальном релизе.

Есть ли смысл Олег Васильевич делать так stati/razdel/stati это зачастую от того, что не думают этот момент, прекрасно можно делать все раздела site.ru/razdel
Олег Васильевич я Олег Васильевич я 12 лет назад #
Комментарий удален
+1
Марат Марат 12 лет назад #
Представленное делает /stati-statia массово на весь компонент без изменения файлов компонента?
Да. Правило вносится только в файл custom_rewrite.php
+2
Марат Марат 12 лет назад #
Теоретически это можно сделать. Но не просто как в примерах. Итак, почему сложно? С site.ru/stati/statia на site.ru/statia у нас идет 301-редирект, а обратно реврайт. То есть для обратного реврайта нам нужно отследить ури site.ru/statia. Но под это описание подходит и site.ru/photos и site.ru/clubs... Страница любого компонента. На этих страницах будет 404. Чтобы этого не было, нужно писать регулярку посложнее. То есть примерно так на словах. Любой ури, не совпадающий с /photos, /clubs... перечисляем компоненты. Если добавите какой-то компонент в систему, придется добавлять и в правило. И черт знает какие еще там есть ури в системе. Поэтому проще сделать site.ru/stati-statia по примеру с поста.
Олег Васильевич я Олег Васильевич я 12 лет назад #
Комментарий удален
-1
Reborn Reborn 12 лет назад #
отличное решение,+++
имею пару вопросов :

1.как сохранить эту вложенность site.ru/stati/categoria/statya.html >>> site.ru/stati/categoria-statya.html (уже имеем,спс) хотя если категория более чем из одного слова,то не работает.

2.и добавить site.ru/stati/category1/category2/statya.html >>> site.ru/stati/category1-category2-statya.html

перепробовал варианты,не выходит (
0
Reborn Reborn 12 лет назад #
по сути происходит подмена ссылок,как бы пс не забанил сайт
-1
Reborn Reborn 12 лет назад #
как то не так выразился.Хотел спросить,а получилось утверждение.
При наведении на ссылку адрес один,а при переходе-другой,тот, что нужен уже.Как к этому отнесутся поисковики ?
В системе есть плагин http://prntscr.com/e6u52 Пример плагина - для роутера /users/get_demo.html
Как то решить бы, чтобы ссылки сразу формировались
+1
Марат Марат 12 лет назад #
• Ɍɕβoṙη •,
При наведении на ссылку адрес один,а при переходе-другой,тот, что нужен уже.Как к этому отнесутся поисковики ?
Думаю, нормально. По первому адресу выдается 301-редирект. По сути он получается навсегда перемещен по второму адресу. Иначе никак не сделать. Страница будет доступна и по второму адресу, но чтобы привести все ссылки ко второму виду, нужно перелопатить файлы самих компонентов. Это уже выходит за рамки данного хака.
1.как сохранить эту вложенность site.ru/stati/categoria/statya.html >>> site.ru/stati/categoria-statya.html (уже имеем,спс) хотя если категория более чем из одного слова,то не работает.
чтобы работало и с категориями более одного слова, нужно в правиле тире "-" заменить другим url-допустимым символом, например знаком подчеркивания "_".
и добавить site.ru/stati/category1/category2/statya.html >>> site.ru/stati/category1-category2-statya.html
Делается по подобию
Код PHP:
  1. $rules[] = array(
  2. 'source' => '/^stati\/(.*?)\/(.*?)\/(.*?)$/is',
  3. 'target' => 'http://ваш_сайт/stati/$1_$2_$3',
  4. 'action' => 'redirect-301'
  5. );
  6. $rules[] = array(
  7. 'source' => '/^stati\/(.*?)_(.*?)_(.*?)$/is',
  8. 'target' => 'stati/$1/$2/$3',
  9. 'action' => 'rewrite'
  10. );
Как то так. Не проверял, но должно работать.
0
Bubble Gumoff Bubble Gumoff 12 лет назад #
А как будет выглядеть обрезка site.ru/shop/category1/category2/statya.html до site.ru/statya ?
0
Марат Марат 12 лет назад #
Шаблонно так не получится. Объясню почему. Простой редирект с site.ru/shop/category1/category2/statya.html на site.ru/statya сделать, нет проблем. Но как же определить урл для обратного реврайта? Страница site.ru/statya будет выдавать 404.
Есть два варианта решить проблему. Первое восользоваться компонентом SEO-pages. Но при этом для каждой страницы будет создаваться отдельное правило. И если у вас там сотни страниц, будет накладно.
Если всё же нужно шаблонно, второй вариант, переписывать файлы компонента. Роутер и контроллер. Если они закрыты, то никак.
0
Bubble Gumoff Bubble Gumoff 12 лет назад #
Жаль Шаблонно так не получится
0
Positive Positive 12 лет назад #
Два вопроса.

1. Работает ли этот хак в ICMS 1.10?

2. Нужно уменьшить вложенность блогов. Излагаю в порядке по приоритету.
В идеале - до корня http://sait.ru/post.html или http://sait.ru/post (без .html)
Если невозможно, то сделать урлы хотя бы двухуровневые
- http://sait.ru/nazvanie-bloga/post.html или http://sait.ru/nazvanie-bloga/post,
- http://sait.ru/blog/post.html или http://sait.ru/blog/post.
Подскажите, может кто знает как это сделать? Много раз на форумах писал, но все говорят о сложностях, а решения нет.

P.S. По статьям подобное решение здесь, в 1.10 работает: http://instantcms.ru/forum/thread6216.html
0
Positive Positive 12 лет назад #
...или, может, есть у кого по блогу другие решения - как уменьшить вложенность?
0
Марат Марат 12 лет назад #
Возможность задания замен по шаблону заложена в самом движке. Даже без этого хака.
Просто не вникал до конца, не посмотрел как реализовано. Этот хак только для приведения шаблонов к виду, привычному в php.
Если делать без хака, то шаблон будет выглядеть примерно так(пример с поста)
Код PHP:
  1. $rules[] = array(
  2. 'source' => '/^users(.*?)$/is',
  3. 'target' => 'http://i19.ru/ludi{1}',
  4. 'action' => 'redirect-301'
  5. );
  6. $rules[] = array(
  7. 'source' => '/^ludi(.*?)$/is',
  8. 'target' => 'users{1}',
  9. 'action' => 'rewrite'
  10. );
Думаю понятна суть.
-1
Reborn Reborn 12 лет назад #
Всё верно, спасиб Марат) только не пойму, зачем Вы адрес сайта прописываете ? Работает и так отлично)
0
Марат Марат 12 лет назад #
Не знаю ) Работает и отлично. У меня возможно из-за слэша не работало ). Просто скопировал то, что было в тестовом файле.
0
Positive Positive 12 лет назад #
Этот пример - users - ludi - работает.
По аналогии со статьями сделал для блога:
Код PHP:
  1. $rules[] = array(
  2. 'source' => '/^blogs\/(.*?)\/(.*?)$/is',
  3. 'target' => '/blogs_{1}_{2}',
  4. 'action' => 'redirect-301'
  5. );
  6. $rules[] = array(
  7. 'source' => '/^blogs\_(.*?)_(.*?)$/is',
  8. 'target' => 'blogs/{1}/{2}',
  9. 'action' => 'rewrite'
  10. );
Получились урлы:
http://sait.ru/blogs_nazvanie-bloga_post-v-bloge.html,
если создать два поста с одинаковыми заголовками, второй получается такой:
http://sait.ru/blogs_nazvanie-bloga_post-v-bloge-10.html.
Это, по идее, хорошо.

Для клубов сделал так:
Код PHP:
  1. $rules[] = array(
  2. 'source' => '/^clubs\/(.*?)$/is',
  3. 'target' => '/clubs_{1}',
  4. 'action' => 'redirect-301'
  5. );
  6. $rules[] = array(
  7. 'source' => '/^clubs\_(.*?)$/is',
  8. 'target' => 'clubs/{1}',
  9. 'action' => 'rewrite'
  10. );
Урлы такие:
http://sait.ru/clubs_14_zapis-v-bloge-kluba.html,
при одинаковых заголовках второй такой: http://sait/clubs_14_zapis-v-bloge-kluba-11.html.

Это намного лучше, чем стандартный вариант. Но, урлы всё же длинными получаются. Может, кто-нибудь знает как убрать звенья из урла? Приведите примеры.
0
Positive Positive 12 лет назад #
Сейчас обнаружил, что после замены /users на другое слово не загружаются аватары... ((
0
Positive Positive 12 лет назад #
Обнаружил, что после Применения этой конструкции вступить в клую не получается - Страница не найдена — 404 (((((. Что нужно сделать, чтобы это устранить? Не хочется клубами жертвовать....
0
Positive Positive 12 лет назад #
Я имею ввиду конструкцию для клубов:
Код PHP:
  1. $rules[] = array(
  2. 'source' => '/^clubs\/(.*?)$/is',
  3. 'target' => '/clubs_{1}',
  4. 'action' => 'redirect-301'
  5. );
  6. $rules[] = array(
  7. 'source' => '/^clubs\_(.*?)$/is',
  8. 'target' => 'clubs/{1}',
  9. 'action' => 'rewrite'
  10. );

Еще от автора

Фильтр "Вставка модуля" v 1.0.0
Приветик! Давненько что-то я ничего не писал ) Не знаю было это или не было, вчера увидел темку, решил сделать немного по-другому. Вещь то нужная.
PHP классы для работы с VK API и с API Яндекс Метрики
Доброго времени суток, коллеги! Выкладываю два класса: -для работы с API Вконтакте; -для работы с API Яндекс Метрики.
Используя этот сайт, вы соглашаетесь с тем, что мы используем файлы cookie.