В Laravel существует несколько типов связей между моделями. Рассмотрим их все на примере отношений между клиентами (Client) и пользователями (User).
1. Один к одному (One-to-One)
Пример: У каждого пользователя может быть только один клиентский профиль, и каждый клиентский профиль принадлежит только одному пользователю.
// В модели User
public function client()
{
return $this->hasOne(Client::class);
}
// В модели Client
public function user()
{
return $this->belongsTo(User::class);
}
Использование:
$user = User::find(1);
$clientProfile = $user->client;
$client = Client::find(1);
$user = $client->user;
2. Один ко многим (One-to-Many)
Пример: Один пользователь может создать много клиентов (например, менеджер создает клиентов).
// В модели User
public function clients()
{
return $this->hasMany(Client::class);
}
// В модели Client
public function user()
{
return $this->belongsTo(User::class);
}
Использование:
$user = User::find(1);
foreach ($user->clients as $client) {
// обработка клиентов
}
$client = Client::find(1);
$creator = $client->user;
3. Многие ко многим (Many-to-Many)
Пример: Многие пользователи могут работать со многими клиентами (отношение сотрудников и клиентов).
// В модели User
public function clients()
{
return $this->belongsToMany(Client::class, 'client_user');
}
// В модели Client
public function users()
{
return $this->belongsToMany(User::class, 'client_user');
}
Промежуточная таблица client_user
должна содержать user_id
и client_id
.
Использование:
$user = User::find(1);
foreach ($user->clients as $client) {
// обработка клиентов
}
$client = Client::find(1);
foreach ($client->users as $user) {
// обработка пользователей
}
4. Has One Through (Один через)
Пример: У пользователя есть один клиент через профиль менеджера.
// В модели User
public function client()
{
return $this->hasOneThrough(
Client::class,
ManagerProfile::class,
'user_id', // Внешний ключ в таблице ManagerProfile
'manager_profile_id', // Внешний ключ в таблице Client
'id', // Локальный ключ в таблице User
'id' // Локальный ключ в таблице ManagerProfile
);
}
5. Has Many Through (Многие через)
Пример: У пользователя много клиентов через отдел.
// В модели User
public function clients()
{
return $this->hasManyThrough(
Client::class,
Department::class,
'user_id', // Внешний ключ в таблице Department
'department_id', // Внешний ключ в таблице Client
'id', // Локальный ключ в таблице User
'id' // Локальный ключ в таблице Department
);
}
6. Полиморфные отношения
Один к одному/многим полиморфные
Пример: И пользователи, и клиенты могут иметь комментарии.
// В модели Comment
public function commentable()
{
return $this->morphTo();
}
// В модели User
public function comments()
{
return $this->morphMany(Comment::class, 'commentable');
}
// В модели Client
public function comments()
{
return $this->morphMany(Comment::class, 'commentable');
}
Многие ко многим полиморфные
Пример: И пользователи, и клиенты могут иметь теги.
// В модели Tag
public function users()
{
return $this->morphedByMany(User::class, 'taggable');
}
public function clients()
{
return $this->morphedByMany(Client::class, 'taggable');
}
// В модели User
public function tags()
{
return $this->morphToMany(Tag::class, 'taggable');
}
// В модели Client
public function tags()
{
return $this->morphToMany(Tag::class, 'taggable');
}
Особенности работы с отношениями
- Жадная загрузка (для оптимизации запросов):
$users = User::with('clients')->get();
- Добавление ограничений:
$activeClients = $user->clients()->where('active', 1)->get();
- Подсчет связанных моделей:
$userWithClientCount = User::withCount('clients')->get();
Каждый тип отношений подходит для разных сценариев взаимодействия между пользователями и клиентами в вашем приложении.