Уроки курса
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 мин

Разработка каталога товаров и категорий

Вывод списка категорий и товаров, реализация пагинации и детальной страницы продукта. Фокус на Project-Based Learning.

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

В этом уроке мы применим подход Project-Based Learning для создания 'сердца' нашего интернет-магазина — каталога товаров. Пользователь должен иметь возможность просматривать все товары, фильтровать их по категориям и переходить на детальную страницу продукта. Проблема, с которой сталкиваются при больших объемах данных, заключается в том, что загрузка тысяч товаров на одну страницу убьет производительность сервера и браузера. Для решения этой проблемы используется Пагинация (разбивка на страницы). Laravel делает этот процесс невероятно простым благодаря встроенному методу paginate() в Eloquent. Кроме того, мы столкнемся с проблемой 'N+1 запросов'. Если мы выведем 20 товаров и для каждого будем запрашивать его категорию в цикле Blade, фреймворк выполнит 1 запрос на товары и 20 запросов на категории. Мы решим это с помощью 'Жадной загрузки' (Eager Loading), используя метод with('category').

php
namespace App\Http\Controllers;

use App\Models\Product;
use Illuminate\Http\Request;
use Illuminate\View\View;

class ProductController extends Controller
{
    public function index(Request $request): View
    {
        // Жадная загрузка категории и пагинация по 12 товаров на страницу
        $query = Product::with('category');

        // Если передана категория в URL, фильтруем по ней
        if ($request->has('category_id')) {
            $query->where('category_id', $request->category_id);
        }

        $products = $query->paginate(12);

        return view('products.index', compact('products'));
    }

    public function show(Product $product): View
    {
        // Laravel автоматически найдет товар по ID благодаря Route Model Binding
        return view('products.show', compact('product'));
    }
}

Разберем код контроллера. В методе index мы используем Product::with('category')->paginate(12). Метод with указывает фреймворку заранее извлечь все связанные категории одним дополнительным SQL-запросом (Eager Loading), что радикально снижает нагрузку на базу данных. Метод paginate(12) берет только 12 записей, соответствующих текущей странице (передается через GET-параметр ?page=2), и возвращает специальный объект LengthAwarePaginator. Этот объект содержит не только сами товары, но и метаданные: общее количество страниц, текущую страницу и методы для генерации HTML-ссылок пагинации. В методе show мы используем магию Laravel под названием 'Route Model Binding'. Обратите внимание: мы передаем в аргументы Product $product. Laravel видит, что мы ожидаем модель, берет ID из URL (например, /products/5) и автоматически выполняет Product::findOrFail(5). Если товар не найден, он сам вернет ошибку 404. Это избавляет нас от написания лишнего шаблонного кода.

html
{{-- Файл: resources/views/products/index.blade.php --}}
@extends('layouts.app')

@section('content')
    <h1>Каталог товаров</h1>
    <div class="product-grid">
        @foreach($products as $product)
            <div class="product-card">
                <h2>{{ $product->name }}</h2>
                <p>Категория: {{ $product->category->name }}</p>
                <p>Цена: ${{ number_format($product->price, 2) }}</p>
                <a href="{{ route('products.show', $product) }}">Подробнее</a>
            </div>
        @endforeach
    </div>

    {{-- Вывод кнопок пагинации --}}
    <div class="pagination-wrapper">
        {{ $products->links() }}
    </div>
@endsection

В шаблоне Blade мы используем директиву @foreach для итерации по массиву товаров. Внутри цикла мы обращаемся к $product->category->name. Благодаря жадной загрузке, которую мы настроили в контроллере, это действие не вызывает новых запросов к БД. Самое интересное находится внизу шаблона: {{ $products->links() }}. Всего одна строчка кода генерирует полноценную, стилизованную (по умолчанию под Tailwind CSS или Bootstrap, в зависимости от настроек) панель навигации по страницам со стрелочками 'Вперед' и 'Назад'. Это отличный пример того, как фреймворк берет на себя рутинную работу, позволяя разработчику сфокусироваться на бизнес-логике проекта.

Какую проблему решает использование метода with('category') при выборке товаров?