Магазин на Yii2, часть 7. Показываем список товаров категории
08.05.2019
Теги: Web-разработка • Yii2 • ИнтернетМагазин • КаталогТоваров • Практика • Фреймворк
Итак, мы вывели на главной странице список лидеров продаж. Теперь покажем список товаров выбранной категории. Нам нужно добавить в модель два метода: один — для получения информации о категории и второй — для получения списка товаров. Или, сделать еще проще — добавить только первый метод, а потом использовать ленивую загрузку, чтобы получить в view-шаблоне массив товаров категории.
Но, обо всем по порядку. Мы добавляем метод, позволяющий получить данные о категории. И у нас описана связь таблицы category
с таблицей product
.
class Category extends ActiveRecord { /** * Метод описывает связь таблицы БД `category` с таблицей `product` */ public function getProducts() { return $this->hasMany(Product::class, ['category_id' => 'id']); } /* * Метод возвращает информацию о категории с идентификатором $id */ public function getCategory($id) { return self::findOne($id); } }
В контроллере нам достаточно получить только данные о категории и передать их в view-шаблон:
class CatalogController extends AppController { public function actionCategory($id) { $id = (int)$id; $category = (new Category())->getCategory($id); return $this->render('category', compact('category')); } }
А данные о товарах категории можно получить прямо в шаблоне views/catalog/category.php
:
// данные о товарах категории с использованием ленивой загрузки $products = $category->products; if (!empty($products)) { echo '<ul>'; foreach ($products as $product) { echo '<li>', $product->name, '</li>'; } echo '</ul>'; } else { echo '<p>Нет товаров в этой категории</p>'; }
Но у нас ситуация несколько сложнее — нужно получить товары не только текущей категории, но и товары во всех потомках этой категории. Т.е. товары дочерних категорий, дочерних дочерних и так далее. Сейчас это стандарт де-факто для каталогов товаров. Поэтому добавим в класс модели метод, возвращающий массив товаров категории с учетом всех ее потомков:
<?php namespace app\models; use yii\db\ActiveRecord; class Category extends ActiveRecord { /** * Метод возвращает имя таблицы БД */ public static function tableName() { return 'category'; } /** * Метод описывает связь таблицы БД `category` с таблицей `product` */ public function getProducts() { return $this->hasMany(Product::class, ['category_id' => 'id']); } /** * Метод описывает связь таблицы БД `category` с таблицей `category` */ public function getParent() { return $this->hasOne(self::class, ['id' => 'parent_id']); } /** * Метод описывает связь таблицы БД `category` с таблицей `category` */ public function getChildren() { return $this->hasMany(self::class, ['parent_id' => 'id']); } /** * Возвращает информацию о категории с иденификатором $id */ public function getCategory($id) { return self::findOne($id); } /** * Возвращает массив товаров в категории с идентификатором $id и во * всех ее потомках, т.е. в дочерних, дочерних-дочерних и так далее */ public function getCategoryProducts($id) { // получаем массив идентификаторов всех потомков категории $ids = $this->getAllChildIds($id); $ids[] = $id; return Product::find()->where(['in', 'category_id', $ids])->all(); } /** * Возвращает массив идентификаторов всех потомков категории $id, * т.е. дочерние, дочерние дочерних и так далее */ protected function getAllChildIds($id) { $children = []; $ids = $this->getChildIds($id); foreach ($ids as $item) { $children[] = $item; $c = $this->getAllChildIds($item); foreach ($c as $v) { $children[] = $v; } } return $children; } /** * Возвращает массив идентификаторов дочерних категорий (прямых * потомков) категории с уникальным идентификатором $id */ protected function getChildIds($id) { $children = self::find()->where(['parent_id' => $id])->asArray()->all(); $ids = []; foreach ($children as $child) { $ids[] = $child['id']; } return $ids; } }
А контроллер у нас будет таким:
<?php namespace app\controllers; use app\models\Category; use app\models\Product; use Yii; class CatalogController extends AppController { /* ... */ /* * Категория каталога товаров */ public function actionCategory($id) { $id = (int)$id; $temp = new Category(); // товары категории $products = $temp->getCategoryProducts($id); // данные о категории $category = $temp->getCategory($id); // устанавливаем мета-теги для страницы $this->setMetaTags( $category->name . ' | ' . Yii::$app->params['shopName'], $category->keywords, $category->description ); return $this->render('category', compact('category', 'products')); } }
Файл view-шаблона views/catalog/category.php
. В нем ничего нового — используем два виджета (меню каталога и популярные бренды) и цикл для показа товаров категории:
<?php /* * Страница раздела каталога, файл views/catalog/category.php */ use app\components\TreeWidget; use app\components\BrandsWidget; use yii\helpers\Html; use yii\helpers\Url; $this->title = $category['name']; ?> <section> <div class="container"> <div class="row"> <div class="col-sm-3"> <div class="left-sidebar"> <h2>Каталог</h2> <div class="category-products"> <?= TreeWidget::widget(); ?> </div> <h2>Бренды</h2> <div class="brand-products"> <?= BrandsWidget::widget(); ?> </div> </div> </div> <div class="col-sm-9"> <?php if (!empty($products)): ?> <h2><?= Html::encode($category['name']); ?></h2> <div class="row"> <?php foreach ($products as $product): ?> <div class="col-sm-4"> <div class="product-wrapper text-center"> <?= Html::img( '@web/images/products/medium/'.$product['image'], ['alt' => $product['name'], 'class' => 'img-responsive'] ); ?> <h2><?= $product['price']; ?> руб.</h2> <p> <a href="<?= Url::to(['catalog/product', 'id' => $product['id']]); ?>"> <?= Html::encode($product['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 else: ?> <p>Нет товаров в этой категории.</p> <?php endif; ?> </div> </div> </div> </section>
- Магазин на Yii2, часть 35. Админка: загрузка картинок для страниц и страница 404
- Магазин на Yii2, часть 34. Показываем меню страниц в публичной части
- Магазин на Yii2, часть 33. Админка: приводим в порядок CRUD-код для страниц
- Магазин на Yii2, часть 32. Админка: удаление категорий и CRUD для страниц
- Магазин на Yii2, часть 31. Админка: загрузка изображений для категорий и брендов
- Магазин на Yii2, часть 30. Админка: WYSIWYG-редактор и изображение для товара
- Магазин на Yii2, часть 29. Админка: добавляем список товаров категории
Поиск: Web-разработка • Yii2 • Интернет магазин • Каталог товаров • Фреймворк