Метод hasOneThrough
Метод hasOneThrough определяет связь "один к одному" через промежуточную модель. Он полезен, когда нужно получить связанную модель, проходя через другую модель. Например, у нас есть три таблицы: mechanics, cars и owners. Механик имеет машину, у машины есть владелец. Мы хотим получить владельца напрямую через механику.
Первым параметром передаётся имя целевой модели, вторым - промежуточная модель, третьим - внешний ключ промежуточной модели, четвёртым - внешний ключ целевой модели, пятым - локальный ключ промежуточной модели, шестым - локальный ключ целевой модели.
Синтаксис
<?php
Model::hasOneThrough(
$related,
$through,
$firstKey = null,
$secondKey = null,
$localKey = null,
$secondLocalKey = null
);
?>
Пример
Давайте определим связь между механиком и владельцем через машину. У каждого механика есть одна машина, у каждой машины есть один владелец. Мы можем получить владельца напрямую через механику:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Mechanic extends Model
{
public function owner()
{
return $this->hasOneThrough(
Owner::class,
Car::class,
'mechanic_id',
'id',
'id',
'owner_id'
);
}
}
?>
Теперь мы можем получить владельца через механику:
<?php
namespace App\Http\Controllers;
use App\Models\Mechanic;
class MechanicController extends Controller
{
public function index()
{
$mechanic = Mechanic::find(1);
$owner = $mechanic->owner;
echo $owner->name;
}
}
?>
Результат выполнения кода:
"John Doe"
Пример
Давайте создадим запрос, который получит всех механиков с их владельцами, у которых name начинается с 'A':
<?php
namespace App\Http\Controllers;
use App\Models\Mechanic;
class MechanicController extends Controller
{
public function index()
{
$mechanics = Mechanic::with('owner')
->whereHas('owner', function ($query) {
$query->where('name', 'like', 'A%');
})
->get();
foreach ($mechanics as $mechanic) {
echo $mechanic->owner->name;
}
}
}
?>
Результат выполнения кода:
["Alice", "Andrew", "Anna"]
Пример
Давайте используем связь для создания нового владельца через механику:
<?php
namespace App\Http\Controllers;
use App\Models\Mechanic;
use App\Models\Owner;
class MechanicController extends Controller
{
public function store()
{
$mechanic = Mechanic::find(1);
$owner = new Owner([
'name' => 'New Owner',
'email' => 'new@example.com'
]);
$car = $mechanic->car;
$car->owner()->save($owner);
}
}
?>
Смотрите также
-
метод
hasOne,
который определяет прямую связь "один к одному" -
метод
hasManyThrough,
который определяет связь "один ко многим" через промежуточную модель -
метод
belongsTo,
который определяет обратную связь "один к одному" -
метод
with,
который выполняет жадную загрузку отношений