Атрибут with
Атрибут with модели позволяет определить отношения, которые должны быть автоматически загружены при каждом извлечении модели из базы данных. Это решает проблему N+1 запросов, когда отношения не загружены заранее, и для каждой модели выполняется отдельный запрос к базе данных. Атрибут принимает массив имён отношений в качестве значения.
Синтаксис
<?php
class ModelName extends Model
{
protected $with = ['relationName'];
}
?>
Пример
Рассмотрим модели Article и Comment. Определим атрибут with для автоматической загрузки комментариев:
<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class Article extends Model
{
protected $with = ['comments'];
public function comments()
{
return $this->hasMany(Comment::class);
}
}
?>
Теперь при получении статей комментарии будут загружены автоматически:
<?php
use AppModelsArticle;
$articles = Article::all();
foreach ($articles as $article) {
foreach ($article->comments as $comment) {
echo $comment->text;
}
}
?>
Результат выполнения кода:
["Comment 1", "Comment 2", "Comment 3"]
Пример
Можно указать несколько отношений для автоматической загрузки. Добавим к статье автора и комментарии:
<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class Article extends Model
{
protected $with = ['author', 'comments'];
public function author()
{
return $this->belongsTo(User::class);
}
public function comments()
{
return $this->hasMany(Comment::class);
}
}
?>
Теперь при получении любой статьи автоматически будут загружены и автор, и комментарии:
<?php
use AppModelsArticle;
$articles = Article::where('status', 'published')->get();
foreach ($articles as $article) {
echo $article->title . ' - ' . $article->author->name;
}
?>
Результат выполнения кода:
["Article 1 - John", "Article 2 - Jane"]
Пример
Можно отключить автоматическую загрузку для конкретного запроса с помощью метода without:
<?php
use AppModelsArticle;
$articles = Article::without('comments')->get();
foreach ($articles as $article) {
echo $article->title;
}
?>
Результат выполнения кода:
["Article 1", "Article 2", "Article 3"]
В этом случае комментарии не будут загружены, что может быть полезно для экономии ресурсов при простом отображении списка статей.
Пример
Можно использовать вложенные отношения с точкой. Загрузим вместе со статьёй автора и его профиль:
<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
class Article extends Model
{
protected $with = ['author.profile'];
public function author()
{
return $this->belongsTo(User::class);
}
}
?>
Теперь при получении статьи будут загружены автор и связанный с ним профиль:
<?php
use AppModelsArticle;
$articles = Article::all();
foreach ($articles as $article) {
echo $article->author->profile->bio;
}
?>
Результат выполнения кода:
["Bio 1", "Bio 2", "Bio 3"]
Смотрите также
-
метод
with,
который добавляет жадную загрузку для конкретного запроса -
метод
load,
который загружает отношение после получения модели -
метод
loadMissing,
который загружает только незагруженные отношения -
метод
without,
который отключает автоматическую загрузку для запроса