OpenCart Multi-Level Menu: Создание многоуровневого меню (CSS + PHP)

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

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

Для начала стоит задуматься о формировании категорий в иерархическом виде, для этого в файл модели категории ~/catalog/model/catalog/category.php добавим функцию getHierarchyCategories():

public function getHierarchyCategories() {

$categories = $this->cache->get('categories.hierarchy.' . (int)$this->config->get('config_language_id') . '.' . (int)$this->config->get('config_store_id'));
if(!$categories) {
$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "category c LEFT JOIN " . DB_PREFIX . "category_description cd ON (c.category_id = cd.category_id) LEFT JOIN " . DB_PREFIX . "category_to_store c2s ON (c.category_id = c2s.category_id) WHERE cd.language_id = '" . (int)$this->config->get('config_language_id') . "' AND c2s.store_id = '" . (int)$this->config->get('config_store_id') . "'  AND c.status = '1' ORDER BY c.sort_order, LCASE(cd.name)");
$rows = $query->rows;
$num_rows = $query->num_rows;
$categories = array();
while($num_rows > 0) {
     foreach ($rows as $key => $row) {
      if ((int)$row['parent_id']) {
       if ($this->addSubcategory($categories, $row)) {
        unset($rows[$key]);
        $num_rows--;
       }
      } else {
       $categories[(int)$row['category_id']] = $row;
        unset($rows[$key]);
        $num_rows--;
      }
     }
    $num_rows--;
   }
   $this->cache->set('categories.hierarchy.' . (int)$this->config->get('config_language_id') . '.' . (int)$this->config->get('config_store_id'), $categories);
  }
  return $categories;
 }


Роль рекурсивной функции здесь выполняет функция addSubcategory(), её код представлен ниже, его также необходимо добавить в файл модели:

 protected function addSubcategory(&$categories, $row) {
  foreach($categories as $category) {
   if ($category['category_id'] == $row['parent_id']) {
    $categories[$row['parent_id']]['children'][$row['category_id']] = $row;
       return true;
   } elseif (!empty($category['children'])) {
      if ($this->addSubcategory($category['children'], $row)) {
       $categories[$category['category_id']]['children'] = $category['children'];
       return true;
      }  
   }
  }
  return false;
 }


Обратите внимание, что функцией getHierarchyCategories() используется кэширование, что не даёт ей злоупотреблять производительностью OpenCart.

Далее в контроллере "шапки" ~/catalog/controller/common/header.php добавляем функции, которые формируют массив данных для выпадающего меню из полученной иерархической структуры категорий:

 protected function addCategories(&$data, $categories, $path = '') {
   foreach($categories as $category) {
        $_path = $path ? ($path . '_' . $category['category_id']) : $category['category_id'];
     $item = array(
       'name'     => $category['name'],
       'column'   => $category['column'] ? $category['column'] : 1,
       'href'     => $this->url->link('product/category', 'path=' . $_path),
       'sort_order'     => $category['sort_order']
      );
     if (!empty($category['children'])) {
      $item['children'] = $this->addCategories($data, $category['children'], $_path);
     }
     if ($category['top']) {
      unset($categories[$category['category_id']]);
      $data[] = $item;
     } else {
      $categories[$category['category_id']] = $item;
     }
   }
    usort($categories, array($this, 'compareSortOrder'));
   return $categories;
 }

 function compareSortOrder($a, $b) {
  return $a['sort_order'] - $b['sort_order'];
 }



Примечание: Функция compareSortOrder($a, $b) используется для сортировки пунктов меню по порядку сортировки категорий.

В этом же файле строку кода $categories = $this->model_catalog_category->getCategories(0); заменяем на код ниже:

$categories = $this->model_catalog_category->getHierarchyCategories();
$this->addCategories($this->data['categories'], $categories);


Блок кода цикла foreach ($categories as $category) полностью удаляем или комментируем. На этом основные работы завершены, остаётся внести соответствующие изменения в шаблон меню ~/catalog/view/theme/default/template/common/header.tpl и файл стилей ~/catalog/view/theme/default/stylesheet/stylesheet.css.

В готовом решении последние шаги уже реализованы и многоуровневое меню (ограничений на количество уровней нет) построено без применения JavaScript, только CSS2. Меню совместимо со всеми популярными браузерами.
Теги:
3 УРОВНЯ, CSS MENU, HIERARCHY, ВЫПАДАЮЩИЙ СПИСОК, ИЕРАРХИЧЕСКОЕ МЕНЮ, КАТЕГОРИИ
Добавлено: 25 Февраля 2015 20:23:10 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...