Реализация корзины покупок
Студент реализует функционал корзины с использованием сессий, научится добавлять товары, менять их количество и считать итоговую сумму.
Концепция сессий в веб-разработке
Протокол HTTP является 'stateless' (без сохранения состояния). Это означает, что сервер не помнит вас между запросами. Когда вы добавляете товар в корзину (запрос 1) и переходите на страницу оформления (запрос 2), сервер должен как-то связать эти два запроса с одним пользователем. Для этого используются Сессии. В Laravel фасад Session предоставляет удобный интерфейс для работы с сессионными данными. Для корзины покупок мы будем использовать массив внутри сессии, где ключом будет ID товара, а значением — массив с данными (имя, цена, количество). Почему сессии, а не база данных? Для гостевых пользователей сессии — идеальный вариант, так как не перегружают БД 'мусорными' корзинами, которые никогда не дойдут до оформления. Принцип Scaffolding: сначала мы создадим простую корзину в сессии, а в будущем вы сможете расширить логику, перенося корзину в БД при авторизации пользователя.
Логика добавления товара
Рассмотрим процесс добавления товара. В контроллере CartController метод add() принимает Request, содержащий product_id. Сначала мы извлекаем текущую корзину из сессии с помощью session()->get('cart', []). Второй аргумент — пустой массив, который вернется, если корзина еще пуста. Далее идет ключевая бизнес-логика: мы проверяем, есть ли уже товар с таким ID в массиве $cart. Если есть (isset($cart[$productId])), мы просто увеличиваем счетчик 'quantity'. Если нет, мы делаем запрос к БД через Product::findOrFail($productId), чтобы получить актуальную цену и название товара, и формируем новый элемент массива. Зачем брать цену из БД, а не передавать из HTML-формы? Это защита от злоумышленников! Если передавать цену из формы, хакер может изменить HTML-код в браузере (через Inspect Element), установить цену 1 копейку и отправить запрос. Всегда доверяйте только данным из вашего бэкенда.
public function add(Request $request) {
$productId = $request->input('product_id');
$cart = session()->get('cart', []);
if (isset($cart[$productId])) {
$cart[$productId]['quantity']++;
} else {
$product = \App\Models\Product::findOrFail($productId);
$cart[$productId] = [
'name' => $product->name,
'price' => $product->price,
'quantity' => 1
];
}
session()->put('cart', $cart);
return redirect()->back()->with('success', 'Товар добавлен в корзину');
}
Вычисление итоговой суммы (Total)
Когда пользователь переходит на страницу корзины, нам необходимо отобразить все товары и посчитать итоговую сумму заказа. В методе index() контроллера CartController мы передаем содержимое сессии в представление. Для расчета суммы можно использовать встроенные функции PHP. В архивных материалах (Упражнение 1.1, Раздел 1) показан отличный пример с использованием array_sum и array_map. Суть в том, чтобы умножить цену каждого товара на его количество, а затем сложить полученные значения. В Blade-шаблоне вы можете перебрать корзину через @foreach(session('cart', []) as $id => $details) и вывести данные. Важно также реализовать методы для удаления конкретного товара (используя unset($cart[$id])) и полного очищения корзины (session()->forget('cart')).
| Хранилище | Плюсы | Минусы |
|---|---|---|
| Сессии (Sessions) | Быстрота работы, не требует запросов к БД, идеально для гостей. | Очищается при закрытии браузера (или истечении lifetime), корзина не синхронизируется между устройствами. |
| База Данных (DB) | Корзина сохраняется навсегда, доступна с мобильного и ПК, аналитика брошенных корзин. | Требует авторизации пользователя, увеличивает нагрузку на базу данных при каждом чихе. |