Уроки курса
1 Основы синтаксиса PHP 8
60 мин
2 Функции и управляющие конструкции
60 мин
3 Объектно-ориентированное программирование на PHP
60 мин
4 Наследование, интерфейсы и полиморфизм
60 мин
5 Основы баз данных MySQL и работа через PDO
60 мин
6 Архитектурный паттерн MVC
60 мин
7 Введение в Laravel и настройка окружения
60 мин
8 Маршрутизация и контроллеры в Laravel
60 мин
9 Шаблонизатор Blade и создание интерфейса
60 мин
10 Миграции баз данных и Eloquent ORM
60 мин
11 Связи моделей в Eloquent — Настройка связей 'один …
60 мин
12 Аутентификация и защита маршрутов
60 мин
13 Разработка каталога товаров и категорий
60 мин
14 Реализация корзины покупок через сессии
60 мин
15 Оформление заказа и транзакции базы данных
60 мин
16 Интеграция платежной системы Stripe
60 мин
17 Интеграция платежной системы Vipps
60 мин
18 Разработка панели администратора
60 мин
19 Оптимизация и подготовка к production
60 мин
20 Деплой Laravel-приложения на сервер
60 мин
21 Основы PHP 8: Синтаксис, переменные и управляющие конструкции
60 мин
22 Функции и массивы в PHP 8
60 мин
23 Объектно-ориентированное программирование: Классы и объекты
60 мин
24 Продвинутое ООП: Наследование, интерфейсы и полиморфизм
60 мин
25 Основы баз данных: Проектирование БД и работа с …
60 мин
26 Взаимодействие PHP с MySQL через PDO
60 мин
27 Архитектура MVC и введение в фреймворк Laravel
60 мин
28 Маршрутизация и контроллеры в Laravel
60 мин
29 Шаблонизатор Blade: Создание пользовательского интерфейса
60 мин
30 Миграции и Eloquent ORM: Создание таблиц товаров
60 мин
31 Связи в Eloquent ORM: Отношения между моделями
60 мин
32 Аутентификация и авторизация пользователей
60 мин
33 Разработка каталога товаров: Вывод, фильтрация и пагинация
60 мин
34 Реализация корзины покупок с использованием сессий
60 мин
35 Оформление заказа: Работа с формами и валидация
60 мин
36 Транзакции базы данных: Сохранение заказа
60 мин
37 Интеграция платежной системы Stripe
60 мин
38 Интеграция платежной системы Vipps
60 мин
39 Создание панели администратора
60 мин
40 Подготовка к production и деплой приложения
60 мин
41 Основы PHP 8 и синтаксис
60 мин
42 Объектно-ориентированное программирование на PHP
60 мин
43 Продвинутое ООП и интерфейсы
60 мин
44 Основы баз данных и MySQL
60 мин
45 Архитектурный паттерн MVC
60 мин
46 Введение в Laravel и маршрутизация
60 мин
47 Шаблонизатор Blade и верстка интерфейса
60 мин
48 Миграции и структура базы данных
60 мин
49 Eloquent ORM и модели
60 мин
50 Отношения в Eloquent ORM
60 мин
51 Авторизация и защита маршрутов
60 мин
52 Создание каталога товаров
60 мин
53 Реализация корзины покупок
60 мин
54 Оформление заказа и транзакции БД
60 мин
55 Интеграция платежной системы Stripe
60 мин
56 Интеграция платежной системы Vipps
60 мин
57 Панель администратора: управление товарами
60 мин
58 Панель администратора: управление заказами
60 мин
59 Подготовка к production и деплой
60 мин
60 Запуск и тестирование готового интернет-магазина
60 мин

Оформление заказа и транзакции БД

Студент напишет логику сохранения заказа в базу данных, используя транзакции для обеспечения атомарности и целостности данных.

Прогресс урока: 0%

Процесс оформления заказа (Checkout)

Оформление заказа — самый ответственный этап работы e-commerce платформы. На этом этапе корзина, временно хранящаяся в сессии, должна превратиться в постоянные записи в базе данных. Согласно нашей архитектуре, мы используем две таблицы: `orders` (хранит общую информацию: ID пользователя, итоговую сумму, статус заказа 'pending') и `order_items` (хранит детали: какой товар, в каком количестве и по какой цене был куплен). Связь между ними — 'один ко многим' (One-to-Many). Один заказ содержит множество позиций. При нажатии кнопки 'Оформить заказ' контроллер CheckoutController должен выполнить следующие действия: 1. Проверить корзину на пустоту. 2. Создать запись в таблице orders. 3. Пройти циклом по корзине и создать записи в order_items, привязав их к ID созданного заказа. 4. Очистить корзину в сессии. 5. Перенаправить пользователя на оплату.

Проблема частичного сохранения и Транзакции

Представьте ситуацию: вы создали запись в таблице `orders`, начали в цикле добавлять `order_items`. Добавили первый товар, а на втором товаре сервер базы данных 'моргнул' или отвалился жесткий диск. Произошла ошибка. В результате в БД остался пустой заказ и только половина товаров. Пользователь оплатит неверную сумму, а менеджер отправит не тот комплект. Это катастрофа для бизнеса. Для решения этой проблемы используются Транзакции Базы Данных. Транзакция гарантирует свойство Атомарности (Atomicity) из принципов ACID: 'Всё или ничего'. Мы оборачиваем весь блок кода с запросами к БД в конструкцию DB::transaction(Closure). Если внутри замыкания происходит любая ошибка (выбрасывается Exception), Laravel автоматически делает 'rollback' — отменяет все изменения, сделанные в рамках этой транзакции. База данных остается в исходном, чистом состоянии. Если всё проходит успешно, выполняется 'commit', и данные фиксируются навсегда.

php
use Illuminate\Support\Facades\DB;
use App\Models\Order;
use App\Models\OrderItem;

public function process() {
    $cart = session('cart', []);
    if (empty($cart)) return redirect()->route('cart.index');

    DB::transaction(function () use ($cart) {
        // Расчет итоговой суммы
        $total = array_sum(array_map(fn($item) => $item['price'] * $item['quantity'], $cart));
        
        // Создание заказа
        $order = Order::create([
            'user_id' => auth()->id(),
            'total_price' => $total,
            'status' => 'pending'
        ]);

        // Создание позиций заказа
        foreach ($cart as $id => $item) {
            OrderItem::create([
                'order_id' => $order->id,
                'product_id' => $id,
                'quantity' => $item['quantity'],
                'price' => $item['price']
            ]);
        }
    });

    // Очистка корзины после успешной транзакции
    session()->forget('cart');
    
    // В следующем уроке здесь будет редирект на Stripe
    return redirect()->route('orders.success');
}

Анализ кода транзакции

Внимательно изучите код выше, взятый из архивных материалов курса. Мы используем анонимную функцию (Closure) внутри DB::transaction. Обратите внимание на конструкцию `use ($cart)`. В PHP анонимные функции по умолчанию не имеют доступа к переменным из родительской области видимости. Мы обязаны явно 'пробросить' переменную $cart внутрь функции. Внутри мы создаем заказ через Eloquent метод create(). Благодаря тому, что мы используем auth()->id(), мы связываем заказ с текущим авторизованным пользователем (именно поэтому маршрут checkout защищен middleware 'auth' из 11 урока). Сразу после создания заказа мы получаем доступ к его идентификатору ($order->id), который используем как внешний ключ (foreign key) при создании записей в цикле foreach для модели OrderItem. Очистка сессии session()->forget('cart') вызывается СТРОГО после успешного завершения транзакции.

Зачем использовать DB::transaction при сохранении заказа?

Задание

Практическая реализация CheckoutController.

  • Создайте модели и миграции для Order и OrderItem (если еще не созданы). Убедитесь, что настроены связи hasMany и belongsTo.
  • В CheckoutController скопируйте логику метода process() из примеров выше.
  • Импортируйте фасад DB в начале файла: use Illuminate\Support\Facades\DB;
  • Проверьте работу, добавив товары в корзину и перейдя по POST-маршруту /checkout.
  • Откройте базу данных (например, через phpMyAdmin или DBeaver) и убедитесь, что записи появились в обеих таблицах с правильными связями по order_id.
10 баллов