Реализация корзины покупок с использованием сессий
Студент создаст функционал корзины, научится добавлять товары, изменять их количество и пересчитывать итоговую сумму, сохраняя данные в сессии.
Управление состоянием: Зачем нужны Сессии?
Протокол HTTP является stateless (без сохранения состояния). Это значит, что каждый запрос к серверу независим, и сервер по умолчанию не помнит, что вы делали секунду назад. Чтобы интернет-магазин работал, нам нужен механизм запоминания товаров, которые пользователь добавил в корзину, пока он бродит по каталогу. Для этого используются Сессии (Sessions).
Сессия — это хранилище данных на стороне сервера, привязанное к конкретному пользователю через уникальный идентификатор (cookie), который хранится в браузере. В Laravel работа с сессиями абстрагирована: мы можем использовать файловую систему, базу данных или Redis для хранения сессий, не меняя код контроллеров. Мы будем использовать фасад session(). Корзина будет представлять собой ассоциативный массив, где ключом является ID товара, а значением — массив с его названием, ценой и количеством.
// App\Http\Controllers\CartController.php
namespace App\Http\Controllers;
use App\Models\Product;
use Illuminate\Http\Request;
class CartController extends Controller {
public function add(Request $request) {
$productId = $request->input('product_id');
// Получаем текущую корзину из сессии или пустой массив, если ее нет
$cart = session()->get('cart', []);
// Если товар уже в корзине, просто увеличиваем количество
if (isset($cart[$productId])) {
$cart[$productId]['quantity']++;
} else {
// Если товара нет, находим его в БД и добавляем в массив
$product = Product::findOrFail($productId);
$cart[$productId] = [
'name' => $product->name,
'price' => $product->price,
'quantity' => 1
];
}
// Сохраняем обновленный массив обратно в сессию
session()->put('cart', $cart);
return redirect()->back()->with('success', 'Товар добавлен в корзину');
}
}
Детальный разбор метода добавления в корзину
Код, представленный выше (из наших архивных упражнений), демонстрирует классический паттерн работы с корзиной в сессии. Обратите внимание на использование метода findOrFail($productId). Это отличная практика: если злоумышленник попытается отправить POST-запрос с несуществующим ID товара, Laravel автоматически выбросит исключение ModelNotFoundException и вернет пользователю страницу 404, прервав выполнение скрипта.
Почему мы храним имя и цену в сессии? Может показаться логичным хранить в сессии только ID товара и его количество, а имя и цену каждый раз брать из БД. Однако хранение базовых данных (имя, цена) в сессии снижает количество запросов к БД при отображении корзины на каждой странице сайта (например, в виджете хедера). Главное правило — при финальном оформлении заказа (Checkout) цену обязательно нужно перепроверять по базе данных, чтобы избежать манипуляций со стороны клиента.
Почему при добавлении нового товара в корзину используется метод Product::findOrFail() вместо Product::find()?
Отображение корзины и подсчет Итого (Total)
Для вывода корзины мы создадим метод index() в CartController, который будет передавать массив session('cart') в представление. В шаблоне Blade мы пройдемся по этому массиву циклом. Одной из частых задач является подсчет общей суммы корзины. Мы можем сделать это прямо в контроллере или в шаблоне.
В PHP есть элегантные способы работы с массивами. Вместо написания цикла foreach для подсчета суммы, мы можем использовать комбинацию функций array_map и array_sum (что мы увидим в следующем уроке при оформлении заказа). Но для отображения в Blade часто достаточно просто умножить цену на количество внутри цикла вывода товаров и прибавлять к промежуточной переменной.
Реализация методов обновления и удаления
Полноценная корзина требует возможности изменять количество товаров и удалять их.
- Создайте маршрут POST /cart/remove и метод remove(Request $request) в CartController.
- В методе remove получите ID товара, проверьте его наличие в session('cart') с помощью isset().
- Используйте функцию unset($cart[$productId]) для удаления элемента массива.
- Сохраните обновленный массив в сессию через session()->put().
- Добавьте кнопку 'Удалить' в Blade-шаблон корзины.