Организация ЧПУ для многоуровневого каталога на сайте?

Занялся вопросом изучения организации ЧПУ на сайте. В принципе все понятно и все ясно. Пишем директивы в .htaccess для того, чтобы все запросы переадресовывались на index.php (точка входа) и уже в index.php обрабатываем поступивший URL (если описывать очень просто).

URl вида /news/2 спомощью функций простейшей функции php разбиваем на массив строк: «news» и «2», с которыми и можем дальше работать. Казалось бы нет ничего проще. Наша программа по первой строке «news» определяет что это новость, а по второй строке «2» определяет идентификатор новости. Вызывается контроллер, отвечающий за вывод новостей, который в свою очередь выдергивает из БД из таблицы новостей нужную нам новость с id=2. Казалось бы все просто. Но не тут то было. Я никак не могу понять и не смог найти в просторах инета решения как быть в следующей ситуации: допустим на сайте есть многоуровневый каталог товаров. Т.к. каталог многоуровневый, то уровней может быть сколько угодно.

/catalog/menu1/menu1/menu2/product или /catalog/menu1/menu2/menu3/menu4/ menu5/product и т. д.

Получив такой URL, мы разбиваем его на массив строк. По первому элементу массива «catalog» мы понимаем, что это каталог и что нужно вызывать контроллер для каталога. Но есть одно «но»…

В случае с новостями мы четко знали что первый элемент «news» — это указание на раздел «новости» (контроллер «новости»), а второй элемент «2» — это указание на идентификатор конкретной новости из таблицы новостей. И структура урла для новостей строго фиксированная. Ну может не совсем фиксированная, может быть еще такой вариант /news (без id новости), но тут нет проблем, т.к. контроллер видит, что в урле есть первый элемент «news» и нет второго (идентификатора новости) и поэтому он понимает что нужно вывести шаблон не вывода конкретной новости, а шаблон вывода списка всех новостей, ну и соответственно выдернуть из базы все новости и вывести их в этот шаблон.

Но как быть с урлом для каталога, когда уровней может быть сколько угодно и фактически контроллер catalog не знает что находится на конце этого урла, т.е. это уже идентификатор конкретного товара (и нужно выводить товар) или же это очередное подменю и нужно выводить список товаров для этого подменю (или список еще одного уровня подменю)?

Например /catalog/la-la-la/tra-ta-ta/bum-bum/za-za – тут наш скрипт понимает, что это каталог, т.к. первый уровень урла на это указывает. Потом пошли разделы каталога la-la-la, tra-ta-ta и т.д. В конце стоит «za-za». И вот тут вопрос: za-za – это что? Это идентификатор очередного подменю или это уже идентификатор продукта. Что делать контроллеру, в какую таблицу лезть, за какой информацией?



Вот этот вопрос я для себя никак не могу прояснить. Может кто-нибудь подскажет какие бывают методики для работы с ЧПУ (желательно в системе MVC), решение этой проблемы.



Например, еще слышал такой подход: урл также разбивается на элементы и каждый элемент указывает на конкретную папку на сервере. Т.е. /catalog/la-la-la/tra-ta-ta/bum-bum/za-za – по сути является путем к директории где лежит контроллер. Но, я так понимаю, что в случае с многоуровневой структурой каталога (или другого какого раздела сайта) данный подход не очень корректен, т.к. не будешь же создавать на сервере папку для каждого подменю.

Была другая мысль: для каждой записи в БД хранить его урл. Например, для продукта «za-za» в таблице продуктов хранить его урл /catalog/la-la-la/tra-ta-ta/bum-bum/za-za. Казалось бы неплохое решение.

Мы в index.php берем наш урл, сравниваем его с урлами товаров из таблицы товаров и если находим продукт с таким урлом, то делаем вывод, что урл ведет к продукту и контроллер catalog выводит на экран шаблон для вывода продукта и в него выводит найденный продукт. Если же контроллер не находит в таблице товаров продукт с таким урлом, то ищет его в таблице разделов каталога и если находит его там, то делает вывод, что это не товар а раздел каталога и также выводит соответствующий шаблон и инфу в него.

Но такой подход тоже не выдерживает никакой критики, т.к. пусть невозможен один и тот же идентификатор у двух товаров или двух подменю, но ведь гипотетически возможна ситуация когда идентификатор какого-либо товара такой же как идентификатор какого либо меню. Или ситуация когда нужно отредактировать один из низжих разделов подменю (например меняем его идентификатор) и получается что у всех дочерних подменю и товаров в урлах в базе данных тоже нужно будет вычленять эти идентификаторы и менять на новые, короче говоря, не дело!



В общем, я в тупике!
  • Вопрос задан
  • 8514 просмотров
Пригласить эксперта
Ответы на вопрос 6
Это разные урлы:

/catalog/la-la-la/tra-ta-ta/bum-bum/za-za
/catalog/la-la-la/tra-ta-ta/bum-bum/za-za/

Может быть от этого «плясать»?

И чтобы было совсем «красиво» можно вот так вот:
/catalog/la-la-la/tra-ta-ta/bum-bum/za-za.html
/catalog/la-la-la/tra-ta-ta/bum-bum/za-za/
Ответ написан
Mobyman
@Mobyman
Есть такая вещь, как nested sets линк на yii behavior, возможно Вам будет полезна.
Ответ написан
Fesor
@Fesor
Full-stack developer (Symfony, Angular)
А почему вы не используете готовые фреймворки (тот же Yii, Symfony2) где эта проблема решена уже?
Ответ написан
xmoonlight
@xmoonlight
https://sitecoder.blogspot.com
Смотрите в сторону деревьев: «узлов» и «листьев» и сразу все станет на свои места. контроллер определяет тип и дальше — уже понятно что делать.
Ответ написан
Комментировать
Я не силен в сео, и не знаю насколько принципиально использовать неограниченную вложенность разделов.
Например, для страницы, имеющей родителей делаю примерно вот так:
/nazvanie-razdela-4c/stranica-97p
где:
nazvanie-razdela — чпу раздела
4 — уникальный ID раздела в таблице
c — идентификатор экшена для отображения раздела (задается в правилах маршрутизации)
stranica — чпу страницы
97 — уникальный ID страницы в таблице
p — идентификатор экшена для отображения страницы (задается в правилах маршрутизации)

Далее, если раздел с чпу nazvanie-razdela вложен в другой раздел, то адрес будет примерно таким:
/roditelskiy-razdel-1c/nazvanie-razdela-4c

Т.е. я отображаю только только текущую страницу и одного ее предка.
Ответ написан
KonstRuctor
@KonstRuctor
программист, дизайнер, фотограф, журналист
Я делал так: www.site.com/catalogue/my_tovar.html
Где my_tovar – уникальный идентификатор товара, который задается при добавлении товара и заносится в базу.
Таким образом мы однозначно попадаем на страницу описания товара.
Сложнее вывести дерево меню слева, но зная id по идентификатору my_tovar, мы ищем полный путь (что вы называется tra-la-la/lala/) и показываем слева дерево меню с открытыми категориями, где искомая категория нашего товара подсвечена class='active'. Для меня именно эта операция была самой непростой, так как не хотелось делать рекурсию при построении сложного дерева.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы