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

Отношения в Eloquent ORM

Настройка связей между таблицами базы данных на уровне классов PHP. Изучение отношений «один ко многим» и решение проблемы N+1 при выборке связанных данных.

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

Связи между моделями (Relationships)

Реляционные базы данных называются так, потому что данные в них связаны между собой. В нашем интернет-магазине Товар (Product) принадлежит определенной Категории (Category), а Заказ (Order) принадлежит Пользователю (User). Eloquent позволяет описывать эти связи прямо в классах моделей в виде методов. Это делает работу со связанными данными невероятно удобной.

Рассмотрим самую частую связь — Один ко многим (One-to-Many). Одна категория (например, 'Смартфоны') может содержать множество товаров. Но один конкретный товар (например, 'iPhone 15') принадлежит только одной категории. Чтобы описать это в Laravel, мы добавляем метод products() в модель Category и используем метод Eloquent hasMany(). Это означает: 'Категория ИМЕЕТ МНОГО товаров'.

Обязательно нужно настроить и обратную связь в модели Product. Для этого мы создаем метод category() (в единственном числе!) и возвращаем belongsTo() ('ПРИНАДЛЕЖИТ'). После настройки этих методов мы сможем обращаться к связанным данным как к динамическим свойствам, например $product->category->name выведет название категории для данного товара.

php
// Файл: app/Models/Category.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;

class Category extends Model
{
    // Категория ИМЕЕТ МНОГО товаров
    public function products() 
    {
        // Указываем класс связанной модели
        return $this->hasMany(Product::class);
    }
}

// Файл: app/Models/Product.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    // Товар ПРИНАДЛЕЖИТ одной категории
    public function category() 
    {
        return $this->belongsTo(Category::class);
    }
}

Проблема N+1 и Жадная загрузка (Eager Loading)

Связи в Eloquent работают по принципу ленивой загрузки (Lazy Loading). Это значит, что данные из связанной таблицы не запрашиваются из базы до тех пор, пока вы явно к ним не обратитесь. И здесь кроется самая распространенная ошибка производительности в Laravel — Проблема N+1 запроса.

Представьте, что вы выводите на главной странице 50 товаров. Вы пишете код $products = Product::all(); (это 1 запрос к БД). Затем в шаблоне Blade вы пишете цикл: @foreach($products as $product) {{ $product->category->name }} @endforeach. Что произойдет под капотом? При каждой итерации цикла, когда вы обращаетесь к ->category, Eloquent будет делать отдельный запрос к БД, чтобы получить категорию именно для этого товара. Итого: 1 запрос на товары + 50 запросов на категории = 51 запрос! Если товаров 1000, будет 1001 запрос. Это катастрофически замедлит загрузку страницы.

Решение — Жадная загрузка (Eager Loading). С помощью метода with() мы заранее говорим Eloquent: 'Получи все товары, и ВМЕСТЕ С НИМИ сразу получи все их категории'. Код будет выглядеть так: Product::with('category')->get();. В этом случае Laravel выполнит всего 2 запроса, независимо от количества товаров: первый выгрузит товары, а второй выгрузит все нужные категории через WHERE IN (...).

php
// --- ПЛОХО: Проблема N+1 (Ленивая загрузка) ---
$products = Product::all(); // Выполняется 1 запрос
foreach ($products as $product) {
    // При каждой итерации выполняется НОВЫЙ запрос к таблице categories
    echo $product->name . ' из категории ' . $product->category->name;
}

// --- ХОРОШО: Жадная загрузка (Eager Loading) ---
// Метод with() принимает имя метода связи из модели Product
$products = Product::with('category')->get(); // Выполняется ровно 2 запроса
foreach ($products as $product) {
    // Запросов к БД больше нет, данные категории уже загружены в память
    echo $product->name . ' из категории ' . $product->category->name;
}

Какой метод Eloquent используется в модели Product для указания того, что товар привязан к одной конкретной категории?

Напишите название метода Eloquent (только слово), который применяется для решения проблемы N+1 путем предварительной (жадной) загрузки связанных моделей.

Задание

Сценарий: Вы разрабатываете страницу категории, на которой должны выводиться все товары, принадлежащие этой категории.

  • В CategoryController найдите нужную категорию: $category = Category::findOrFail($id);
  • Вместо того чтобы делать отдельный запрос к таблице товаров, используйте связь.
  • Получите товары через динамическое свойство: $products = $category->products;
  • Передайте обе переменные в шаблон Blade: return view('category.show', compact('category', 'products'));
10 баллов