Laravel по-русски

Русское сообщество разработки на PHP-фреймворке Laravel.

Ты не вошёл. Вход тут.

#1 10.03.2017 22:46:18

Ленивая и жадная загрузки. Различия.

В чем отличие, помимо того, что жадная загрузка затрачивает меньше ресурсов?

Стоит ли мне всё время юзать жадную загрузку?

Не в сети

#2 11.03.2017 15:37:43

Re: Ленивая и жадная загрузки. Различия.

смотри тут какое дело, в любой СУБД выбрать все нужные записи одним запросом намного эффективнее чем по одной записи за запрос. если например у тебя есть модели Post и User и у тебя на постах связь author() на пользователей, ты наверняка выбрал все посты одним запросом по нужным условиям (фильтры, сортировки, пагинация) и выводишь их в шаблоне:

@foreach ($posts as $post)
  <div class="post">
    <div class="post__title">{{ $post->title }}</div>
    <div class="post__author>{{ $post->author()->name }}</div>
  </div>
@endforeach

если ты не загружал авторов «жадно» – каждая итерация в цикле будет дёргать базу за одним пользователем по его идентификатору в $post->author_id. если связей больше и выборки идут глубже на связи связей – запросов может оказаться просто буран. я видел страницы, генерящие тысячи запросов в базу при открытии – это крайне неэффективно. однажды пользователей станет достаточно много чтобы нагрузка на сервер вышла из-под контроля.

жадная загрузка решает эту проблему. если выбрать Post::with('author') или на выбранных постах сделать $posts->load('author') элоквент сделает одну простую вещь – соберёт идентификаторы всех пользователей авторов для выбранной группы постов, загрузит их всех одним запросом и прилепит в каждый пост его автора (т.н. «насыщение» моделей – hydrate). количество запросов станет меньше, нагрузка снизится, скорость отдачи страницы возрастёт. with() и load() позволяют выбирать и вложенные связи, например если у пользователя есть связь type() с моделью UserType, можно на постах выбрать сразу Post::with(['author', 'author.type']).

с ленивой и жадной загрузками всё просто – если выбираешь больше одной записи и потом группу записей выводишь в цикле со связанными моделями – все связи должны быть загружены жадно. если в данном примере отображается только один пост, например, то загружать или не загружать его автора заранее – вопрос вкуса, для простоты кода, можно без этого обойтись (в этом случае если связь станет не нужна – она не будет загружаться, автоматически после удаления из вида), можно взять за правило всегда загружать все данные заранее и явно, и никогда не выполнять никаких запросов в видах (в этом случае если связь в виде станет не нужна, код загружающий её надо будет удалять). в первом случае у тебя магия которая просто работает, во втором – больший контроль сложности, поддерживаемость кода и отсутствие разных «сюрпризов» когда что-то работало «само» а потом сломалось – тоже «само». эти сюрпризы сжирают время разработчика так неожиданно и много, что лично мой выбор – второй вариант, по крайней мере для коммерческих проектов. для хобби и экспериментов – там я пишу вообще как попало иногда, лишь бы быстрее запустить smile

Не в сети

#3 17.03.2017 08:16:50

Re: Ленивая и жадная загрузки. Различия.

Batya пишет:

Стоит ли мне всё время юзать жадную загрузку?

@constb дал широкий ответ, но не ответил на вопрос.

Инструкция:
1) Изначально всегда используй жадную загрузку.
2) При проблемах - экспериментируй.

т.е. для того чтобы использовать ленивую загрузку - должны быть причины.

Не в сети

#4 03.12.2018 05:42:10

Re: Ленивая и жадная загрузки. Различия.

Помогите, пожалуйста, составить жадный запрос. Laravel 5.6.31

Есть такие таблицы

pagetypes
    id
    ru_name
    sef_name

pagetype_service
    id
    page_id
    pagetype_id
    service_id

pages
    id
    title
    h1
    ...

services
    id
    category_id
    sef_url
    price
    ...

сategories
    id
    parent_id
    sef_url
    ...

Модели уже есть Pagetype, Page, Service и Category, а таблица pagetype_service создана для связей. В моделях уже прописаны соответствующие связи с другими моделями. Можно и дописать если надо.

Нужно получить все страницы, которые соответствуют определённому типу из таблицы PAGETYPES. Я имею определённый sef_name.

Нужно получить все PAGES, но которые в таблице PAGETYPE_SERVICE имеют pagetype_id равную соответствующему id полученному по sef_name из таблицы PAGETYPES.
Тамже в таблице PAGETYPE_SERVICE есть поле service_id - это связь каждой страницы с таблицей SERVICES, и нужно получить соответствующие данные для каждой страницы
А в таблице SERVICES есть поле category_id, которое является связью с таблицей СATEGORIES и нужно получить эти данные тоже

Возможно такое сделать в одном запросе?

Изменено Michael007 (03.12.2018 05:52:20)

Не в сети

Подвал раздела