Связывание нескольких моделей Eloquent Laravel

В прошлой статье "Связывание моделей Eloquent Laravel" мы привели примеры связывания один к одному, один к многим, многие к одному. В этой статье продолжим разбираться с темой и изучим связывание "многие к многим". Но сначала углубим знания по "один ко многим":

Один ко многим "через"

Мы уже рассматривали метод связывания "один ко многим" - hasMany. Метод "hasManyThrough" позволяет сделать связывание сразу нескольким моделей с указанием полей, даже если не все таблицы имеют поля, указывающие друг на друга.

Предположим, что у нас есть следующие таблицы со столбцами (типы данных указаны напротив названий столбцов, а в скобках записаны названия таблиц):
[countries]
   id - integer
   name - string

[users]
   id - integer
   country_id - integer
   name - string

[posts]
   id - integer
   user_id - integer
   title - string
Как видно, таблица posts не содержит поля country_id. Но отношение "ко многим через" позволит получить доступ к posts через country: $country->posts. Для выполнения такого запроса Eloquent найдёт country_id в таблице users, и получит совпадающие id с значанием user_id в таблице posts.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Country extends Model {
   public function posts() {
      return $this->hasManyThrough('App\Post', 'App\User');
   }
}
?>
Первый параметр метода "hasManyThrough" является именем конечной модели, а второй параметр - это имя промежуточной. Если нужно вручную указать ключи для моделей, то третий параметр - это имя ключа промежуточной модели, четвёртый - имя ключа конечной модели, а пятый - локальный ключ. Для нашего примера это будет выглядеть так:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Country extends Model {
   public function posts() {
      return $this->hasManyThrough(
         'App\Post', 'App\User',
         'country_id', 'user_id', 'id'
      );
   }
}
?>

Многие ко многим

Представим случай, при котором нужно выполнить связывание "многие ко многим". Примером послужит разграничение пользователей по ролям. Предположим, что есть три таблицы: users, roles и role_user. Последняя имеет только два столбца user_id и role_id и служит для того, чтобы можно было узнать у какого пользователя какая роль.

Приведём пример получения роли пользователя:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model {
   public function roles() {
      return $this->belongsToMany('App\Role');
   }
}
?>
Тогда для получения данных ролей пользователя можно использовать следующий код:
<?php
$user = App\User::find(1);

foreach ($user->roles as $role) {
  // данные о ролях пользователя
}
?>
Вторым параметром метода belongsToMany можно переопределить ключ для связывания (иначе будет использовано название таблицы). Третий аргумент - это имя внешнего ключа модели, на которой определяется отношение. Четвертый аргумент - это внешний ключ модели, с которой будет связан:
<?php
return $this->belongsToMany(
   'App\Role', 
   'role_user', 'user_id', 'role_id'
);
?>
Теперь чтобы решить обратную задачу и получить пользователей по роли, можно написать такой код:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Role extends Model {
   public function users() {
      return $this->belongsToMany('App\User');
   }
}
?>
Как можно догадаться, связывание "многие ко многим" требует дополнительной таблицы. Eloquent предоставляет несколько способов взаимодействия с этой промежуточной таблицей. Приведём пример.

Предположим, что объект User связан со многими объектами Role. После задания связи можно получить доступ к промежуточной таблице с помощью атрибута модели под названием "pivot":
<?php
$user = App\User::find(1);

foreach ($user->roles as $role) {
   echo $role->pivot->created_at;
}
?>
При получении модели Role ей автоматически присваивается атрибут pivot. Атрибут содержит модель промежуточной таблицы. С ней можно работать точно так же, как и с любой другой моделью.

Если промежуточная "pivot" таблица содержит дополнительные атрибуты, то необходимо указать их при определении отношения:
<?php
return $this->belongsToMany('App\Role')->withPivot('column1', 'column2');
?>
Если от таблицы "pivot" требуется поддержка временных меток created_at и updated_at, то необходимо использовать метод "withTimestamps" при определении отношения:
<?php
return $this->belongsToMany('App\Role')->withTimestamps();
?>
Так же для промежуточной таблицы доступны методы для фильтрации "wherePivot" и "wherePivotIn". Они работают точно так же, как и обычные "where" и "whereIn", но их необходимо указать при определении отношения:
<?php
return $this->belongsToMany('App\Role')->wherePivot('food', 'cheese');
return $this->belongsToMany('App\Role')->wherePivotIn('animal', ['mouse', 'cat']);
?>
MouseDC.ru - хостинг, виртуальный хостинг, покупка доменов, проверка доменов, WHOIS, курсы создания сайтов, вебинары по созданию, курсы разработки сайтов, доработка сайтов, сопровождение сайтов, разработка сайтов, техподдержка сайтов
Cмотрите другие статьи:
Была ли статья полезной?
Была ли эта статья полезна? Есть вопрос?
хостинг для сайтов
Закажите недорогой хостинг Заказать

всего от 290 руб