Магазин на Yii2, часть 17. Корзина покупателя, часть первая
13.07.2019
Теги: Session • Web-разработка • Yii2 • ИнтернетМагазин • КаталогТоваров • Корзина • Практика • Форма • Фреймворк
Ну вот, добрались и до корзины. Перед тем, как писать код — несколько слов о том, что будем делать. Для начала создадим форму для добавления товара в корзину из списка товаров категории, бренда, результатов поиска. Контроллер будет принимать POST-данные и обращаться к модели, чтобы добавить товар в корзину. Саму корзину будем хранить в сессии в виде массива.
Итак, создаем класс контроллера BasketController
:
<?php namespace app\controllers; use app\models\Basket; use Yii; class BasketController extends AppController { public function actionIndex() { $basket = (new Basket())->getBasket(); return $this->render('index', ['basket' => $basket]); } public function actionAdd() { $basket = new Basket(); /* * Данные должны приходить методом POST; если это не * так — просто показываем корзину */ if (!Yii::$app->request->isPost) { return $this->redirect(['basket/index']); } $data = Yii::$app->request->post(); if (!isset($data['id'])) { return $this->redirect(['basket/index']); } if (!isset($data['count'])) { $data['count'] = 1; } // добавляем товар в корзину и перенаправляем покупателя // на страницу корзины $basket->addToBasket($data['id'], $data['count']); return $this->redirect(['basket/index']); } }
Создаем класс модели Basket
:
<?php namespace app\models; use yii\base\Model; use Yii; class Basket extends Model { /** * Метод добавляет товар в корзину */ public function addToBasket($id, $count = 1) { $count = (int)$count; if ($count < 1) { return; } $id = abs((int)$id); $product = Product::findOne($id); if (empty($product)) { return; } if ($count > 10) { $count = 10; } $session = Yii::$app->session; $session->open(); if (!$session->has('basket')) { $session->set('basket', []); $basket = []; } else { $basket = $session->get('basket'); } if (isset($basket['products'][$product->id])) { // такой товар уже есть? $count = $basket['products'][$product->id]['count'] + $count; if ($count > 100) { $count = 100; } $basket['products'][$product->id]['count'] = $count; } else { // такого товара еще нет $basket['products'][$product->id]['name'] = $product->name; $basket['products'][$product->id]['price'] = $product->price; $basket['products'][$product->id]['count'] = $count; } $amount = 0.0; foreach ($basket['products'] as $item) { $amount = $amount + $item['price'] * $item['count']; } $basket['amount'] = $amount; $session->set('basket', $basket); } /** * Метод удаляет товар из корзины */ public function removeFromBasket($id) { $id = abs((int)$id); $session = Yii::$app->session; $session->open(); if (!$session->has('basket')) { return; } $basket = $session->get('basket'); if (!isset($basket['products'][$id])) { return; } unset($basket['products'][$id]); if (count($basket['products']) == 0) { $session->set('basket', []); return; } $amount = 0.0; foreach ($basket['products'] as $item) { $amount = $amount + $item['price'] * $item['count']; } $basket['amount'] = $amount; $session->set('basket', $basket); } /** * Метод возвращает содержимое корзины */ public function getBasket() { $session = Yii::$app->session; $session->open(); if (!$session->has('basket')) { $session->set('basket', []); return []; } else { return $session->get('basket'); } } /** * Метод удаляет все товары из корзины */ public function clearBasket() { $session = Yii::$app->session; $session->open(); $session->set('basket', []); } }
Создаем view-шаблон для страницы корзины:
<?php /* * Страница корзины покупателя, файл views/basket/index.php */ use app\components\TreeWidget; use app\components\BrandsWidget; use yii\helpers\Html; use yii\helpers\Url; ?> <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>Корзина</h1> <?php if (!empty($basket)): ?> <table class="table table-bordered"> <tr> <th>Наименование</th> <th>Количество</th> <th>Цена, руб.</th> <th>Сумма, руб.</th> </tr> <?php foreach ($basket['products'] as $item): ?> <tr> <td><?= $item['name']; ?></td> <td class="text-right"><?= $item['count']; ?></td> <td class="text-right"><?= $item['price']; ?></td> <td class="text-right"><?= $item['price'] * $item['count']; ?></td> </tr> <?php endforeach; ?> <tr> <td colspan="3" class="text-right">Итого</td> <td class="text-right"><?= $basket['amount']; ?></td> </tr> </table> <?php else: ?> <p>Ваша корзина пуста</p> <?php endif; ?> </div> </div> </div> </section>
Формат корзины, которую мы храним в сессии (123
и 456
— идентификаторы товаров):
Array ( [products] => Array( [123] => Array ( [name] => Мужская рубашка [price] => 1000 [count] => 2 ) [456] => Array( [name] => Мужская футблока [price] => 1200 [count] => 1 ) ) [amount] => 3200 )
Кроме всего прочего, изменяем файлы view-шаблонов, где показывается список товаров — добавляем форму. Например, вот как будет выглядеть файл views/catalog/category.php
:
<?php /* * Страница раздела каталога, файл views/catalog/category.php */ use app\components\TreeWidget; use app\components\BrandsWidget; use app\components\ChainWidget; use yii\helpers\Html; use yii\helpers\Url; use yii\widgets\LinkPager; ?> <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"> <?= ChainWidget::widget(['itemCurrent' => $category['id'], 'showCurrent' => false]); ?> <?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> <form method="post" action="<?= Url::to(['basket/add']); ?>"> <input type="hidden" name="id" value="<?= $product['id']; ?>"> <?= Html::hiddenInput( Yii::$app->request->csrfParam, Yii::$app->request->csrfToken ); ?> <button type="submit" class="btn btn-warning"> <i class="fa fa-shopping-cart"></i> Добавить в корзину </button> </form> <?php if ($product['new']) { // новинка? echo Html::img( '@web/images/home/new.png', ['alt' => 'Новинка', 'class' => 'new'] ); } if ($product['sale']) { // распродажа? echo Html::img( '@web/images/home/sale.png', ['alt' => 'Распродажа', 'class' => 'sale'] ); } ?> </div> </div> <?php endforeach; ?> </div> <?= LinkPager::widget(['pagination' => $pages]); /* постраничная навигация */ ?> <?php else: ?> <p>Нет товаров в этой категории.</p> <?php endif; ?> </div> </div> </div> </section>
Обратите внимание на скрытое поле со значением CSRF токена. Это нужно, чтобы не получить ошибку:
Bad Request (#400). Не удалось проверить переданные данные.
На этом все, корзина для списка товаров уже работает.
- Магазин на Yii2, часть 21. Оформление заказа, часть вторая
- Магазин на Yii2, часть 20. Оформление заказа, часть первая
- Магазин на Laravel 7, часть 10. Форма оформления, сохранение заказа в базу данных
- Магазин на Yii2, часть 22. Оформление заказа, часть третья
- Магазин на Yii2, часть 19. Корзина покупателя, часть третья
- Магазин на Yii2, часть 18. Корзина покупателя, часть вторая
- Магазин на Laravel 7, часть 24. Фильтр товаров категории по цене, новинкам и лидерам продаж
Поиск: Session • Web-разработка • Yii2 • Интернет магазин • Каталог товаров • Практика • Форма • Фреймворк • Корзина • Сессия