hasManyThrough дістає записи через проміжну модель - коли прямого зовнішнього ключа немає.
Приклад: проєкт має середовища, середовища мають деплої. Потрібні всі деплої проєкту.
projects environments deployments
id id, project_id id, environment_id
class Project extends Model
{
public function deployments(): HasManyThrough
{
return $this->hasManyThrough(Deployment::class, Environment::class);
}
}
$project->deployments; // один запит з JOIN через environments
Чому не вручну: $project->environments->flatMap->deployments завантажить усі середовища, а потім деплої окремими запитами. Зв'язок робить один запит і, як будь-який зв'язок, підтримує with(), withCount() і whereHas().
Порядок ключів, якщо імена нестандартні, - найчастіше джерело плутанини:
return $this->hasManyThrough(
Deployment::class,
Environment::class,
'project_id', // ключ у environments
'environment_id', // ключ у deployments
'id', // локальний ключ у projects
'id', // локальний ключ у environments
);
Читабельніша альтернатива - через уже наявні зв'язки: $this->through('environments')->has('deployments'). Для одного запису є hasOneThrough.