Магазин на Yii2, часть 3. Виджет для вывода меню каталога
04.05.2019
Теги: Web-разработка • Yii2 • Виджет • ИнтернетМагазин • КаталогТоваров • Плагин • Практика • Фреймворк
Теперь нам нужно как-то выводить меню каталога в левой колонке. Поскольку это меню показывается на многих страницах сайта, реализуем его в виде виджета. И тогда сможем вставить меню в любом месте шаблона одной строкой кода. Для создания виджета нам потребуется директория components
, внутри нее создаем файл класса TreeWidget.php
.
<?php namespace app\components; use yii\base\Widget; use app\models\Category; use Yii; /** * Виджет для вывода дерева разделов каталога товаров */ class TreeWidget extends Widget { /** * Выборка категорий каталога из базы данных */ protected $data; /** * Массив категорий каталога в виде дерева */ protected $tree; public function run() { // пробуем извлечь данные из кеша $html = Yii::$app->cache->get('catalog-menu'); if ($html === false) { // данных нет в кеше, получаем их заново $this->data = Category::find()->indexBy('id')->asArray()->all(); $this->makeTree(); if ( ! empty($this->tree)) { $html = $this->render('tree', ['tree' => $this->tree]); } else { $html = ''; } // сохраняем полученные данные в кеше Yii::$app->cache->set('catalog-menu', $html, 60); } return $html; } /** * Функция принимает на вход линейный массив элеменов, связанных * отношениями parent-child, и возвращает массив в виде дерева */ protected function makeTree() { if (empty($this->data)) { return; } foreach ($this->data as $id => &$node) { if ( ! $node['parent_id']) { $this->tree[$id] = &$node; } else { $this->data[$node['parent_id']]['childs'][$id] = &$node; } } } }
all()
возвращается массив строк, индексированный последовательными целыми числами. Чтобы сделать индекс по указанному столбцу, нужно вызвать метод indexBy()
перед вызовом метода all()
.
Теперь создаем шаблон menu.php
для меню каталога в директории components/views
:
<?php /* * Файл components/views/menu.php */ use yii\helpers\Html; use yii\helpers\Url; ?> <ul id="accordion"> <?php foreach ($tree as $item1): ?> <li><a href="<?= Url::to(['catalog/category', 'id' => $item1['id']]); ?>"> <?= Html::encode($item1['name']); ?> <?php if (isset($item1['childs'])): ?> </a> <span class="badge pull-right"><i class="fa fa-plus"></i></span> <ul> <?php foreach ($item1['childs'] as $item2): ?> <li><a href="<?= Url::to(['catalog/category', 'id' => $item2['id']]); ?>"> <?= Html::encode($item2['name']); ?> <?php if (isset($item2['childs'])): ?> </a> <span class="badge pull-right"><i class="fa fa-plus"></i></span> <ul> <?php foreach ($item2['childs'] as $item3): ?> <li><a href="<?= Url::to(['catalog/category', 'id' => $item3['id']]); ?>"> <?= Html::encode($item3['name']); ?> <?php if (isset($item3['childs'])): ?> </a> <span class="badge pull-right"><i class="fa fa-plus"></i></span> <ul> <?php foreach ($item3['childs'] as $item4): ?> <li><a href="<?= Url::to(['catalog/category', 'id' => $item4['id']]); ?>"> <?= Html::encode($item4['name']); ?> <?php if (isset($item4['childs'])): ?> </a> <span class="badge pull-right"><i class="fa fa-plus"></i></span> <ul> <?php foreach ($item4['childs'] as $item5): ?> <li><a href="<?= Url::to(['catalog/category', 'id' => $item5['id']]); ?>"> <?= Html::encode($item5['name']); ?></a></li> <?php endforeach; ?> </ul> <?php else: ?> </a> <?php endif; ?> </li> <?php endforeach; ?> </ul> <?php else: ?> </a> <?php endif; ?> </li> <?php endforeach; ?> </ul> <?php else: ?> </a> <?php endif; ?> </li> <?php endforeach; ?> </ul> <?php else: ?> </a> <?php endif; ?> </li> <?php endforeach; ?> </ul>
Осталось только добавить вызов виджета в view-шаблоне views/site/index.php
:
<h2>Каталог</h2> <?= TreeWidget::widget(); ?>
Для того, чтобы элементы меню можно было свернуть и развернуть, создадим файл accordion.js
и сохраним его в директории web/js
. Для стилевого оформления меню создадим файл accordion.css
и сохраним его в директории web/css
.
jQuery(document).ready(function($) { $('#accordion ul').hide(); $('#accordion .badge').on('click', function () { var $badge = $(this); var closed = $badge.siblings('ul') && !$badge.siblings('ul').is(':visible'); if (closed) { $badge.siblings('ul').slideDown('normal', function () { $badge.children('i').removeClass('fa-plus').addClass('fa-minus'); }); } else { $badge.siblings('ul').slideUp('normal', function () { $badge.children('i').removeClass('fa-minus').addClass('fa-plus'); }); } }); });
#accordion {
list-style: none;
padding-left: 0;
}
#accordion ul {
list-style: none;
}
#accordion .badge {
cursor: pointer;
}
И подключим эти два файла подключаем к нашему комплекту ресурсов:
<?php namespace app\assets; use yii\web\AssetBundle; use yii\web\View; /** * Main application asset bundle */ class AppAsset extends AssetBundle { public $basePath = '@webroot'; public $baseUrl = '@web'; public $css = [ 'css/font-awesome.min.css', 'css/accordion.css', 'css/main.css' ]; public $js = [ 'js/accordion.js', 'js/main.js' ]; public $depends = [ 'yii\web\YiiAsset', 'yii\bootstrap\BootstrapPluginAsset', ]; public function registerAssetFiles($view) { /*.....*/ } }
Мы использовали метод хелпера Url::to()
для создания ссылок на разделы каталога. Сейчас ссылка имеет вид
http://www.server.com/catalog/category?id=123
Давайте изменим ее на
http://www.server.com/catalog/category/123
Для этого изменяем правила роутинга в файле конфигурации config/web.php
:
$config = [ /*...*/ 'components' => [ /*...*/ 'urlManager' => [ 'enablePrettyUrl' => true, 'showScriptName' => false, 'rules' => [ 'catalog/category/<id:\d+>' => 'catalog/category' ], ], /*...*/ ], /*...*/ ];
- Магазин на Yii2, часть 13. Страница товара и хлебные крошки
- Магазин на Yii2, часть 35. Админка: загрузка картинок для страниц и страница 404
- Магазин на Yii2, часть 34. Показываем меню страниц в публичной части
- Магазин на Yii2, часть 33. Админка: приводим в порядок CRUD-код для страниц
- Магазин на Yii2, часть 32. Админка: удаление категорий и CRUD для страниц
- Магазин на Yii2, часть 31. Админка: загрузка изображений для категорий и брендов
- Магазин на Yii2, часть 30. Админка: WYSIWYG-редактор и изображение для товара
Поиск: Web-разработка • Yii2 • Виджет • Интернет магазин • Каталог товаров • Плагин • Фреймворк