Ларавель - Красномовні «Має», «З», «Де?» - Що вони означають?


211

Я визнав, що поняття та значення цих методів є дещо заплутаним, чи можна комусь пояснити мені, в чому полягає різниця між hasі withв контексті прикладу (якщо це можливо)?

Відповіді:


555

З

with()призначений для нетерплячого завантаження . Це в основному означає, що вздовж основної моделі Laravel буде попередньо завантажувати вказані вами відносини. Це особливо корисно, якщо у вас є колекція моделей і ви хочете завантажити відношення для всіх. Тому що з нетерплячим завантаженням ви запускаєте лише один додатковий запит БД замість одного для кожної моделі колекції.

Приклад:

User > hasMany > Post

$users = User::with('posts')->get();
foreach($users as $user){
    $users->posts; // posts is already loaded and no additional DB query is run
}

Має

has()- фільтрувати модель вибору на основі співвідношення. Таким чином, він діє дуже схоже на нормальний стан, де БЕЗ. Якщо ви просто використовуєте has('relation')це означає, що ви хочете отримати лише моделі, які мають принаймні одну пов'язану модель у цьому відношенні.

Приклад:

User > hasMany > Post

$users = User::has('posts')->get();
// only users that have at least one post are contained in the collection

Де він

whereHas()працює в основному так само, як has()але дозволяє вказати додаткові фільтри для перевірки відповідної моделі.

Приклад:

User > hasMany > Post

$users = User::whereHas('posts', function($q){
    $q->where('created_at', '>=', '2015-01-01 00:00:00');
})->get();
// only users that have posts from 2015 on forward are returned

101
+1, дуже корисна відповідь! Зауважте також, що поки with('relation')будуть включені дані пов'язаної таблиці у повернену колекцію, has('relation')і whereHas('relation')вони не включатимуть дані пов'язаної таблиці. Тому вам може знадобитися зателефонувати with('relation')як і, has()або whereHas().
Soulriser

1
Привітайте відповідь, як отримати доступ до батьківської моделі з моделі відносин, наприклад, тут, як шукати поштову модель на основі атрибутів моделі користувача
hussainfrotan

@BhojendraNepal На жаль, у документах, здається, немало про це ... Це все, що я знайшов (це кілька абзаців вниз)
lukasgeiter

@hussainfrotan так само, використовуйте whereHasдля відношення користувачів під час запиту повідомлення.
Майкл Цанг

Цікаво, що в документації Laravel: laravel.com/docs/5.8/eloquent-relationships , коли з whereHasїї допомогою використовується те, use Illuminate\Database\Eloquent\Builder;що потім є function(Builder $query). Більшість прикладів, які я бачив, використовую крапки Builder, просто передайте в $ запиті, що це правильний шлях?
Гунтар

8

Документ вже пояснив використання. Тому я використовую SQL для пояснення цих методів

Приклад:


Якщо припустити, що існує Order (orders)багато OrderItem (order_items).

І ви вже будуєте відносини між ними.

// App\Models\Order:
public function orderItems() {
    return $this->hasMany('App\Models\OrderItem', 'order_id', 'id');
}

Ці три методи базуються на взаємозв'язку .

З


Результат: with() поверніть об'єкт моделі та пов'язані з цим результати.

Перевага: Це нетерпляче завантаження, яке може запобігти проблемі N + 1 .

Коли ви використовуєте такий красномовний Builder:

Order::with('orderItems')->get();

Laravel змінив цей код лише на два SQL :

// get all orders:
SELECT * FROM orders; 

// get the order_items based on the orders' id above
SELECT * FROM order_items WHERE order_items.order_id IN (1,2,3,4...);

А потім laravel об'єднує результати другого SQL за відмінними від результатів першого SQL за допомогою зовнішнього ключа . Нарешті поверніть результати колекції.

Отже, якщо ви вибрали стовпці без іноземного ключа на завершення, результат відносин буде порожнім:

Order::with(['orderItems' => function($query) { 
           // $query->sum('quantity');
           $query->select('quantity'); // without `order_id`
       }
])->get();

#=> result:
[{  id: 1,
    code: '00001',
    orderItems: [],    // <== is empty
  },{
    id: 2,
    code: '00002',
    orderItems: [],    // <== is empty
  }...
}]

Має


Hasповерне об’єкт моделі, що його відносини не порожні .

Order::has('orderItems')->get();

Laravel змінить цей код на один SQL :

select * from `orders` where exists (
    select * from `order_items` where `order`.`id` = `order_item`.`order_id`
)

де він


whereHasта orWhereHasспособи встановити whereумови для ваших hasзапитів. Ці методи дозволяють додавати спеціальні обмеження для обмеження відносин .

Order::whereHas('orderItems', function($query) {
   $query->where('status', 1);
})->get();

Laravel змінить цей код на один SQL :

select * from `orders` where exists (
    select * 
    from `order_items` 
    where `orders`.`id` = `order_items`.`order_id` and `status` = 1
)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.