Ruslan Brest, rb.labtodo.com
Backend web-developer: CodeIgniter, PHP, MySQL, OpenCart, PrestaShop, MaxSite CMS

Opencart 1.5.1.x (catalog): как вывести третий уровень категорий в главном меню

Просмотров: 18919 RSS 30
Howto » OpenCart

UPD 2015-01: Статья написана в 2011 году для актуальных тогда версий OpenCart. Для более новых описанные изменения могут не подойти. Скорей всего описанные изменения актуальны для всех oc151x (делалось на них), может быть до oc153x (не уверен). Есть информация о том, что для v1564 не подходит. Я не пользовался всей этой линейкой версий и соответственно не делал для них изменения. Если не получается разобраться, можно нанять меня, за 10-15 WMZ сделаю для вашей версии.

Если используется тема, отличная от default, изменения надо производить в её файлах, разумеется (css, tpl). И только в случае отсутствия их в используемой теме их следует искать в default. И в этом случае может понадобиться индивидуальный подход, поскольку CSS может значительно отличаться. Так что будьте особенно аккуратны, делайте резервные копии изменяемых файлов.

Имейте в виду, что оригинальное решение, принятое в Опенкарт, очень неоптимальное по производительности и при большом количестве категорий и товаров этот блок надо переделать и сделать совершенно по-другому. Здесь показан способ, использующий стандартный механизм Опенкарт.

 

diff --git a/public_html/catalog/controller/common/header.php b/public_html/catalog/controller/common/header.php
index 21bfe6f..a603a5f 100644
--- a/public_html/catalog/controller/common/header.php
+++ b/public_html/catalog/controller/common/header.php
@@ -200,10 +200,11 @@ class ControllerCommonHeader extends Controller {
 									
 					$children_data[] = array(
 						'name'  => $child['name'] . ' (' . $product_total . ')',
-						'href'  => $this->url->link('product/category', 'path=' . $category['category_id'] . '_' . $child['category_id'])	
-					);					
+						'href'  => $this->url->link('product/category', 'path=' . $category['category_id'] . '_' . $child['category_id']),
+						'children' => $this->getChildrenData($child['category_id'], $category['category_id'])	// rb, 2011-09-03: menu 3rd level
+					);
 				}
-				
+
 				// Level 1
 				$this->data['categories'][] = array(
 					'name'     => $category['name'],
@@ -237,6 +238,28 @@ class ControllerCommonHeader extends Controller {
 		}
 		
     	$this->render();
-	} 	
+	}
+
+	// http://rb.labtodo.com/, 2011-09-03: menu 3rd level
+	private function getChildrenData( $ctg_id, $path_prefix )
+	{
+		$children_data = array();
+		$children = $this->model_catalog_category->getCategories($ctg_id);
+
+		foreach ($children as $child) {
+			$data = array(
+				'filter_category_id'  => $child['category_id'],
+				'filter_sub_category' => true
+			);
+
+			$product_total = $this->model_catalog_product->getTotalProducts($data);
+
+			$children_data[] = array(
+				'name'  => $child['name'] . ' (' . $product_total . ')',
+				'href'  => $this->url->link('product/category', 'path=' . $path_prefix . '_' . $child['category_id'])
+			);
+		}
+		return $children_data;
+	}
 }
 ?>
\ No newline at end of file
diff --git a/public_html/catalog/view/theme/default/stylesheet/stylesheet.css b/public_html/catalog/view/theme/default/stylesheet/stylesheet.css
index ecee15b..3f89efa 100644
--- a/public_html/catalog/view/theme/default/stylesheet/stylesheet.css
+++ b/public_html/catalog/view/theme/default/stylesheet/stylesheet.css
@@ -343,7 +343,9 @@ label {
 #menu > ul > li > a.active {
 	background: #000;
 }
-#menu > ul > li > a {
+#menu > ul > li > a
+/*#menu > ul > li > div > ul > li > a*/
+{
 	font-size: 13px;
 	color: #FFF;
 	line-height: 14px;
@@ -353,7 +355,8 @@ label {
 	z-index: 6;
 	position: relative;
 }
-#menu > ul > li > div {
+#menu > ul > li > div
+{
 	display: none;
 	background: #FFFFFF;
 	position: absolute;
@@ -366,16 +369,39 @@ label {
 	border-radius: 0px 0px 5px 5px;
 	background: url('../image/menu.png');
 }
-#menu > ul > li:hover > div {
+#menu > ul > li > div > ul > li > div
+{
+	display: none;
+	background: #FFFFFF;
+	position: absolute;
+	z-index: 5;
+	padding: 5px;
+	margin-left: 50px;
+	border: 1px solid #000000;
+	-webkit-border-radius: 0px 0px 5px 5px;
+	-moz-border-radius: 0px 0px 5px 5px;
+	-khtml-border-radius: 0px 0px 5px 5px;
+	border-radius: 0px 0px 5px 5px;
+	background: url('../image/menu.png');
+}
+#menu > ul > li:hover > div,
+#menu > ul > li:hover > div > ul > li:hover > div
+{
 	display: table;
 }
-#menu > ul > li > div > ul {
+#menu > ul > li > div > ul,
+#menu > ul > li > div > ul > li > div > ul
+{
 	display: table-cell;
 }
-#menu > ul > li ul + ul {
+#menu > ul > li ul + ul,
+#menu > ul > li ul > li ul + ul
+{
 	padding-left: 20px;
 }
-#menu > ul > li ul > li > a {
+#menu > ul > li ul > li > a,
+#menu > ul > li ul > li ul > li > a
+{
 	text-decoration: none;
 	padding: 4px;
 	color: #FFFFFF;
@@ -386,9 +412,12 @@ label {
 #menu > ul > li ul > li > a:hover {
 	background: #000000;
 }
-#menu > ul > li > div > ul > li > a {
+#menu > ul > li > div > ul > li > a,
+#menu > ul > li > div > ul > li > div > ul > li > a
+{
 	color: #FFFFFF;
 }
+
 .breadcrumb {
 	color: #CCCCCC;
 	margin-bottom: 10px;
diff --git a/public_html/catalog/view/theme/default/template/common/header.tpl b/public_html/catalog/view/theme/default/template/common/header.tpl
index eef4ae7..d93120a 100644
--- a/public_html/catalog/view/theme/default/template/common/header.tpl
+++ b/public_html/catalog/view/theme/default/template/common/header.tpl
@@ -123,7 +123,17 @@ DD_belatedPNG.fix('#logo img');
           <?php $j = $i + ceil(count($category['children']) / $category['column']); ?>
           <?php for (; $i < $j; $i++) { ?>
           <?php if (isset($category['children'][$i])) { ?>
-          <li><a href="<?php echo $category['children'][$i]['href']; ?>"><?php echo $category['children'][$i]['name']; ?></a></li>
+          <li><a href="<?php echo $category['children'][$i]['href']; ?>"><?php echo $category['children'][$i]['name']; ?></a>
+            <?php if( $category['children'][$i]['children'] ) { ?>
+            <div>
+              <ul>
+              <?php foreach( $category['children'][$i]['children'] as $menu3item ) { ?>
+              <li><a href="<?php echo $menu3item['href']; ?>"><?php echo $menu3item['name']; ?></a></li>
+              <?php } ?>
+              </ul>
+            </div>
+            <?php } ?>
+          </li>
           <?php } ?>
           <?php } ?>
         </ul>
twitter.com facebook.com vkontakte.ru odnoklassniki.ru mail.ru ya.ru digg.com friendfeed.com liveinternet.ru livejournal.ru yandex.ru del.icio.us
Комментариев: 30
  1. Здравствуйте, Руслан!

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

    Спасибо большое за Ваш труд!!!

  2. 2011-09-26 в 22:15:57 | Ruslan Brest

    Не помню... Проверил - нет, только для главного меню сделано. Сбоку модуль категорий выводит только 1-й и 2-й уровни.

    UPD. См. http://rb.labtodo.com/page/opencart-1512-modul-kategorij-tretij-uroven-bez-optimizacii-zaprosov

  3. а можно ли вообще вывод третьей категории в боковом меню? Стоит ли заморачиваться поиском решения?

  4. 2011-09-27 в 06:46:39 | Ruslan Brest

    Можно вообще всё :) Было бы желание и время.

    UPD. См. http://rb.labtodo.com/page/opencart-1512-modul-kategorij-tretij-uroven-bez-optimizacii-zaprosov

  5. 2011-10-17 в 03:28:36 | Аноним

    не совсем понятно, а что в этой записи измененно?

    -#menu > ul > li > div {

    +#menu > ul > li > div

    +{

    display: none;

    background: #FFFFFF;

    position: absolute;

    @@ -366,16 +369,39 @@ label {

    border-radius: 0px 0px 5px 5px;

    background: url('../image/menu.png');

    }

  6. 2011-10-17 в 03:29:17 | Аноним

    И что это ? @@ -386,9 +412,12 @@ label {

  7. 2011-10-17 в 04:15:32 | Ruslan Brest

    Скобка перенесена. Видимо, экспериментировал, а потом убрал лишнюю строку, а скобка перенесённой осталась.

    @@ -386,9 +412,12

    это примерные номера строк с изменениями и ещё какая-то доп. информация для diffutils. Примерные - потому что нумерация у меня и у других может быть разной из-за разных модификаций.

    @@ label {

    это функция, в которой это изменение встретилось. Для PHP - обычно имя функции или класса, в HTML/CSS/TPL сюда попадает что-то на них похожее. Можно использовать для ориентира и доп. контроля.

  8. 2011-10-18 в 04:58:28 | Аноним

    Скажите пожалуйста, как сделать что бы если в меню 2 строчки категорий, нижняя строчка категорий не мешала выпадающему меню верхних категорий, вот у меня на сайте такая проблема Сайт http://tuningdom.ru, Помогите.

  9. 2011-10-18 в 05:15:15 | Ruslan Brest

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

  10. Уважаемый Руслан!

    Спасибо за интересное решение. Помогите, пожалуйста.

    Можно ли в модуле категорий указать, из какой категории нужно отображать категории. То есть, у меня трехуровневый каталог: категория -> подкатегория -> товар

    В модуле нужно вывести раскрытую категорию, в которой бы отображались ссылки на подкатегории.

  11. 2011-11-11 в 04:30:09 | Ruslan Brest

    То есть категорий получается две? Категория и подкатегория. Товары - в списке выводятся на странице. Или как-то не так?

    То ли я не понял задачу, то ли это и так делается без переделок: одна категория верхнего уровня и все подкатегории в ней. Они и будут всегда раскрыты и показаны.

  12. Вот здесь ошибка

    > 'children' => $this->getChildrenData($child['category_id'], $category['category_id'])

    Так на opencart 1.5.1.3 не заходит в категории 3 уровня.

    Должно быть:

    'children' => $this->getChildrenData($child['category_id'], $category['category_id']. '_' . $child['category_id'])

  13. 2012-03-23 в 05:06:07 | Ruslan Brest

    Ок, спасибо. На 1512 работает, на 1513 руки не доходили поставить, как раз скоро понадобится, проверю.

    Только вот глядя на ошибку, думаю, причина не в версии. У вас скорей всего osCtore и SeoPro? Я не пользуюсь, поэтому скорей всего у меня другие результаты будут.

  14. да ocStore, seo обычный. Сам подумал, что ошибка возможно не в этом. Сейчас модуль seo разбираю.

  15. У меня почему-то после каждой категории выводится производители :(

    Есть скрин, но сюда его не встаить

    Как излечить? Версия 1.5.2

  16. 2012-06-09 в 10:00:16 | Сергей

    Спасибо за данное решение!!

    Пробовал сделать всё на ocStore 1.5.2.1 всё сделал по вашей инструкции, всё правильно, проверял не один раз. Само меню заработало, уровни работают прекрасно, но при заходе на страницу в третьем уровне, пишет "Запрашиваемая страница не найдена!"

    Отключаю SEOpro, ссылка в виде .ru/ford/ranger/dvigatel, сама страница отображается в третьем меню, но вот товара нет "В этой категории нет товаров." Отключаю все SEO настройки и всё заработало и третий уровень и товар стал отображаться :-) но это безусловно не решение проблемы... видимо надо править сам .htaccess, а вот что там подправить к сожалению не знаю (( Руслан, может вы поможете ? наводку дал )

    Заранее благодарен за спасение !! ;-)

  17. 2012-06-09 в 19:57:36 | Ruslan Brest

    С SeoPro я не пробовал. С оригинальным SeoUrl, как включенным, так и отключенным, проблем быть не должно.

    На 1.5.2 тоже не смотрел ещё.

  18. У меня ругается на строку

    <?php if( $category['children'][$i]['children'] ) { ?>

    Undefined index: children

  19. 2012-09-02 в 00:56:54 | Ruslan Brest
    Undefined index: children

    Значит в контроллере этот новый элемент не заполняется. Проверьте ещё раз, все ли правки внесены.

  20. Как сделать чтобы третий уровень выводился не под вторым (чьим потомком он является), а на против?

  21. Добрый день. Скажите как всем уровням вложенности сделать вывод картинок, которые добавляются в админке для категорий. Спасибо!

  22. Спасибо за статью. Все прекрасно подошло для ocStore 1.5.5.1.1. Только стили stylesheet.css оставила без изменений, так как с предложенными изменениями у меня дизайн уехал. Вот бы еще найти такое же раскрытие для модуля категорий в боковом меню.

  23. 2013-12-27 в 03:31:41 | Ruslan Brest

    У меня где-то было и про модуль категорий. Гугл подсказывает:

    http://rb.labtodo.com/page/opencart-1512-modul-kategorij-tretij-uroven-bez-optimizacii-zaprosov

    Тоже для старой версии, так что на 1.5.5 пробуйте самостоятельно.

    Но вообще-то в ocStore работу с категориями кажется должны были оптимизировать: меньше запросов, кеширование и всё такое. Так что может там совсем другой код. И я бы не рекомендовал возвращать назад работу с категориями с ocStore-вской на Opencart-овскую реализацию.

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

  24. Сделала модуль категорий, как в http://rb.labtodo.com/page/opencart-1512-modul-kategorij-tretij-uroven-bez-optimizacii-zaprosov. Тоже работает для ocStore 1.5.5.1.1. Так что спасибо!

  25. 2013-12-27 в 07:46:16 | Ruslan Brest

    Отлично! Рад :)

    Спасибо за информацию, надо будет дописать это в статьи.

  26. Что-то ноль реакции на изменения) Сделал по Вашей инструкции, а подкатегорию не показывает http://xn----8sbacd7adi9aa3b3i.xn--p1ai/ Подкатегорию создавал для вино/испания/пьемонт

  27. 2014-04-14 в 02:24:04 | Ruslan Brest

    Ну так у Вас и шаблон - далеко не Default. Как в нём меню генерируется, я не знаю и могу только догадываться по тому, что доступно в броузере.

    То, что третий уровень вообще не появился в коде верхнего меню, свидетельствует о том, что исправления внесены явно не все. Или не туда.

    Если бы туда -- скорей всего дизайн бы перекосило или выпадало много лишнего. Так как разница CSS этого шаблона и дефолтного скорей всего ну очень уж большая. Но я и в HTML-коде страницы не вижу намёков на элементы третьего уровня у вина, так что они туда банально не попадают.

  28. Версия 1,5,6,4 не заработала.

    Инструкция полная лажа.

    Пишите нормально.

    Находим код (блаблалаа)

    Заменяем на (все пуском)

  29. 2015-01-08 в 12:19:33 | Ruslan Brest

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

    Ухудшать универсальное описание изменений в сторону стиля "найдите то, замените на это" не планирую. Делать vQmod-ы тоже. Выложить сделаный кем-то vQmod для предпочитающих этот путь - могу. Некоторые предлагали, спасибо им за это.

    За информацию про v1564 - спасибо. Смотрите на дату выхода статьи - это 2011 год. Ожидать, что она подойдёт без всяких проблем к версиям, появившимся в 2014 - как минимум странно. Информацию в заголовке поправлю.

  30. Есть 1 вариант таков, только в данном случае Вы удалите лишь надпись " В этой категории нет товаров" , а кнопка "Продолжить" останется.

    В админке создаем статью: "Каталог-Статьи -Добавить статью -Называем статью -во вкладке Данные пишем SEO URL: к примеру contacts", во вкладке Дизайн -выбираем соответствующий "селект-пункт из выпадающего меню" - "Информация" для страницы "Доставка и Оплата", а для контактов - селект "Контакты", после заходим в настройки темы шаблона : Дополнения-Модули-Настройки темы- выбираем вкладку "Главное меню", в самом низу есть графа: "Пользовательская ссылка" - нажимаем плюсик, пишем название категории "Контакты", в строке ссылка вставляем нашу ссылку, которую Мы присваивали ранее созданной статье "contacts" и устанавливаем порядок сортировки, сохраняем и все работает. Всем удачи.

Оставьте комментарий!

Используйте нормальные имена. Ваш комментарий будет опубликован после проверки.

Имя и сайт используются только при регистрации

Если вы уже зарегистрированы как комментатор или хотите зарегистрироваться, укажите пароль и свой действующий email. При регистрации на указанный адрес придет письмо с кодом активации и ссылкой на ваш персональный аккаунт, где вы сможете изменить свои данные, включая адрес сайта, ник, описание, контакты и т.д., а также подписку на новые комментарии.

Авторизация  Facebook. MaxSiteAuth. Loginza

(обязательно)