Отложенная и жадная загрузка


Пример 1 - выполняется много запросов для каждого customer

// SELECT * FROM `customer` LIMIT 100
$customers = Customer::find()->limit(100)->all();

foreach ($customers as $customer) {
    // SELECT * FROM `order` WHERE `customer_id` = ...
    $orders = $customer->orders;
}

Пример 2 - Выполняется один запрос для всех customer

// SELECT * FROM `customer` LIMIT 100;
// SELECT * FROM `orders` WHERE `customer_id` IN (...)
$customers = Customer::find()
    ->with('orders')
    ->limit(100)
    ->all();

foreach ($customers as $customer) {
    // SQL-запрос не выполняется
    $orders = $customer->orders;
}

Другие примеры

// жадная загрузка "orders" и "country" одновременно
$customers = Customer::find()->with('orders', 'country')->all();
// аналог с использованием синтаксиса массива
$customers = Customer::find()->with(['orders', 'country'])->all();
// SQL-запрос не выполняется
$orders= $customers[0]->orders;
// SQL-запрос не выполняется
$country = $customers[0]->country;

// жадная загрузка связи "orders" и вложенной связи "orders.items"
$customers = Customer::find()->with('orders.items')->all();
// доступ к деталям первого заказа первого покупателя
// SQL-запрос не выполняется
$items = $customers[0]->orders[0]->items;

В жадных запросах можно использовать анонимные функции для уточнения

// найти покупателей и получить их вместе с их странами и активными заказами
// SELECT * FROM `customer`
// SELECT * FROM `country` WHERE `id` IN (...)
// SELECT * FROM `order` WHERE `customer_id` IN (...) AND `status` = 1
$customers = Customer::find()->with([
    'country',
    'orders' => function ($query) {
        $query->andWhere(['status' => Order::STATUS_ACTIVE]);
    },
])->all();