Магазин на Yii2, часть 13. Страница товара и хлебные крошки
12.06.2019
Теги: Web-разработка • Yii2 • Виджет • ИнтернетМагазин • КаталогТоваров • Навигация • Практика • Фреймворк • ХлебныеКрошки
Следующий этап — создаем модель, контроллер и представление для показа страницы товара. Для снижения нагрузки полученные от модели данные кешируем в контроллере. Заодно добавим хлебные крошки для страницы товара и для раздела каталога. Для этого создадим виджет ChainWidget
и будем вызывать его в view-шаблонах товара и категории.
Контроллер, модель и представление для товара
<?php namespace app\controllers; use app\models\Category; use app\models\Brand; use app\models\Product; use Yii; class CatalogController extends AppController { /*...*/ /** * Страница товара с идентификатором $id */ public function actionProduct($id) { $id = (int)$id; // пробуем извлечь данные из кеша $data = Yii::$app->cache->get('product-'.$id); if ($data === false) { // данных нет в кеше, получаем их заново $product = (new Product())->getProduct($id); $brand = (new Brand())->getBrand($product['brand_id']); $data = [$product, $brand]; // сохраняем полученные данные в кеше Yii::$app->cache->set('product-'.$id, $data); } list($product, $brand) = $data; // устанавливаем мета-теги $this->setMetaTags( $product['name'] . ' | ' . Yii::$app->params['shopName'], $product['keywords'], $product['description'] ); // получаем товары, похожие на текущий $similar = Yii::$app->cache->get('similar-'.$product['id']); if ($similar === false) { // товары из той же категории того же бренда $similar = Product::find() ->where([ 'category_id' => $product['category_id'], 'brand_id' => $product['brand_id'] ]) ->andWhere(['NOT IN', 'id', $product['id']]) ->limit(3) ->asArray() ->all(); Yii::$app->cache->set('similar-'.$product['id'], $similar); } return $this->render( 'product', compact('product', 'brand', 'similar') ); } }
<?php namespace app\models; use yii\db\ActiveRecord; class Product extends ActiveRecord { /** * Возвращает имя таблицы БД */ public static function tableName() { return 'product'; } /** * Возвращает родительскую категорию */ public function getCategory() { // связь таблицы БД `product` с таблицей `category` return $this->hasOne(Category::class, ['id' => 'category_id']); } /** * Возвращает информацию о товаре с иденификатором $id */ public function getProduct($id) { return self::find()->where(['id' => $id])->asArray()->one(); } }
<?php /* * Страница товара, файл views/catalog/product.php */ use app\components\TreeWidget; use app\components\BrandsWidget; use app\components\ChainWidget; use yii\helpers\Url; use yii\helpers\Html; ?> <section> <div class="container"> <div class="row"> <div class="col-sm-3"> <h2>Каталог</h2> <div class="category-products"> <?= TreeWidget::widget(); ?> </div> <h2>Бренды</h2> <div class="brand-products"> <?= BrandsWidget::widget(); ?> </div> </div> <div class="col-sm-9"> <h1><?= Html::encode($product['name']); ?></h1> <div class="row"> <div class="col-sm-5"> <div class="product-image"> <?= Html::img( '@web/images/products/large/'.$product['image'], ['alt' => $product['name'], 'class' => 'img-responsive'] ); ?> </div> </div> <div class="col-sm-7"> <div class="product-info"> <p class="product-price"> Цена: <span><?= $product['price']; ?></span> руб. </p> <form> <label>Количество</label> <input name="count" type="text" value="1" /> <button type="button" class="btn btn-warning"> <i class="fa fa-shopping-cart"></i> Добавить в корзину </button> </form> <p>Артикул: 1234567</p> <p>Наличие: На складе</p> <p> Бренд: <a href="<?= Url::to(['catalog/brand', 'id' => $brand['id']]); ?>"> <?= Html::encode($brand['name']); ?> </a> </p> </div> </div> </div> <div class="product-descr"> <?= $product['content']; ?> </div> <?php if (!empty($similar)): /* похожие товары */ ?> <h2>Похожие товары</h2> <div class="row"> <?php foreach ($similar as $item): ?> <div class="col-sm-4"> <div class="product-wrapper text-center"> <?= Html::img( '@web/images/products/medium/'.$item['image'], ['alt' => $item['name'], 'class' => 'img-responsive'] ); ?> <h2><?= $item['price']; ?> руб.</h2> <p> <a href="<?= Url::to(['catalog/product', 'id' => $item['id']]); ?>"> <?= Html::encode($item['name']); ?> </a> </p> <a href="#" class="btn btn-warning"> <i class="fa fa-shopping-cart"></i> Добавить в корзину </a> <?php if ($product['new']) { // новинка? echo Html::tag( 'span', 'Новинка', ['class' => 'new'] ); } if ($product['hit']) { // лидер продаж? echo Html::tag( 'span', 'Лидер продаж', ['class' => 'hit'] ); } if ($product['sale']) { // распродажа? echo Html::tag( 'span', 'Распродажа', ['class' => 'sale'] ); } ?> </div> </div> <?php endforeach; ?> </div> <?php endif; ?> </div> </div> </div> </section>
Хлебные крошки
Создаем файл components/ChainWidget.php
:
<?php namespace app\components; use app\models\Category; use yii\base\Widget; use Yii; /** * Виджет для вывода цепочки навигации (хлебные крошки) */ class ChainWidget extends Widget { /** * Идентификатор текущей категории */ public $itemCurrent; /** * Показывать текущую категорию? */ public $showCurrent = true; public function run() { if (empty($this->itemCurrent)) { return ''; } // пробуем извлечь данные из кеша $show = $this->showCurrent ? 'true' : 'false'; $key = 'widget-chain-'.$this->itemCurrent.'-show-'.$show; $html = Yii::$app->cache->get($key); if ($html === false) { // данных нет в кеше, получаем их заново $chain = (new Category())->getParents($this->itemCurrent); if (!$this->showCurrent) { array_pop($chain); } $html = $this->render('chain', ['chain' => $chain]); // сохраняем полученные данные в кеше Yii::$app->cache->set($key, $html); } return $html; } }
И создаем файл components/views/chain.php
<?php /* * Файл components/views/brands.php */ use yii\helpers\Html; use yii\helpers\Url; if (empty($chain)) { return; } ?> <ol class="breadcrumb"> <?php foreach ($chain as $item): ?> <li> <a href="<?= Url::to(['catalog/category', 'id' => $item->id]); ?>"> <?= Html::encode($item->name); ?> </a> </li> <?php endforeach; ?> </ol>
Вызов виджета для страницы категории каталога:
<?= ChainWidget::widget(['itemCurrent' => $category['id'], 'showCurrent' => false]); ?>
Вызов виджета для страницы товара каталога:
<?= ChainWidget::widget(['itemCurrent' => $product['category_id']]); ?>
- Магазин на Yii2, часть 10. Добавляем постраничную навигацию
- Магазин на Yii2, часть 3. Виджет для вывода меню каталога
- Магазин на Laravel 7, часть 20. Показ отдельной страницы и верхнее меню всех страниц
- Магазин на Yii2, часть 35. Админка: загрузка картинок для страниц и страница 404
- Магазин на Yii2, часть 34. Показываем меню страниц в публичной части
- Магазин на Yii2, часть 33. Админка: приводим в порядок CRUD-код для страниц
- Магазин на Yii2, часть 32. Админка: удаление категорий и CRUD для страниц
Поиск: Web-разработка • Yii2 • Виджет • Интернет магазин • Каталог товаров • Навигация • Практика • Фреймворк • Хлебные крошки