Как правильно связать две модели со сводной таблицей?

Есть модели:
  • User - модель пользователя
  • Role - модель роли
  • RoleSettings - модель настроек, соответствующих определенной роли

Модель базы данных:
Открыть изображение
5f67aacb4c78a364042421.png


Логика работы следующая:
  1. Создаем роли
    Role::create([
            "name" => "Пользователь",
            "slug" => "user"
          ]);


  2. Создаем настроки роли, которые будут потом добавлены каждому пользователю, у которого соответствующая роль (например, пользователь может включить/отключить уведомление о комментариях в ветке, а администратор включить/уведомления уведомления о новых постах на почту)
    RoleSettings::create([
            'setting_title' => 'Уведомлять о новых ответах в комментариях',
            'setting_slug' => 'comment_reply_enabled',
            'role_id' => Role::where('slug','user')->first()->id
          ]);


  3. Добавляем роль пользователю
    $role = Role::where('slug','user')->first();
    $user->role()->attach($role);


  4. Далее мне надо из таблицы roles_settings добавить в таблицу users_settings все записи, у которых role_id равна role_id пользователя, и указать для этих записей соответствующий id пользователя.
    Пока это реализовано так:
    /**
          * Прикрепляем пользователю роль по умолчанию (пользователь)
          */
          $user_settings = [];
          $role_settings = RoleSettings::where('role_id',1)->get();
    
          foreach ($role_settings as $role_setting) {
            $user_settings[$role_setting->id] = ['value' => $role_setting->default_value];
          }
    
          $user->settings()->attach($user_settings);




В принципе, это работает, но объект пользователя будет такой:
Показать объект
"id": 1,
        "name": "Sklyarov Alexey",
        "email": "---",
        "email_verified_at": null,
        "current_team_id": null,
        "profile_photo_path": "profile-photos/mU1dOnx7YhDWY5OEAxRKgkijwRghRW7XgI7Rp5IT.jpeg",
        "created_at": "2020-09-19T12:22:28.000000Z",
        "updated_at": "2020-09-19T12:26:46.000000Z",
        "profile_photo_url": "http://localhost/storage/profile-photos/mU1dOnx7YhDWY5OEAxRKgkijwRghRW7XgI7Rp5IT.jpeg",
        "settings": [
            {
                "id": 1,
                "role_id": 1,
                "setting_title": "Уведомлять о новых ответах в комментариях",
                "setting_slug": "comment_reply_enabled",
                "default_value": 1,
                "pivot": {
                    "user_id": 1,
                    "setting_id": 1,
                    "value": "1"
                }
            },
            {
                "id": 2,
                "role_id": 1,
                "setting_title": "Уведомлять о новых ответах на почту",
                "setting_slug": "comment_reply_mail_enabled",
                "default_value": 1,
                "pivot": {
                    "user_id": 1,
                    "setting_id": 2,
                    "value": "1"
                }
            }
        ],


То есть информация, которая мне нужна первоначально, находится в pivot. Очевидно это связано с тем, как я связываю настройки ролей с пользователем. В модели User делаю я это так:
/**
    * Получить настройки пользователя
    */
    public function settings()
    {
      return $this->belongsToMany(RoleSettings::class,'users_settings','user_id','setting_id')->withPivot('value');
    }


Не понимаю, как связать эти модели адекватно.
  • Вопрос задан
  • 87 просмотров
Пригласить эксперта
Ответы на вопрос 2
Kulaxyz
@Kulaxyz
Могу лучше
Посмотри, как реализовано в готовых пакетах, например тут
Если я правильно понял, то это решение ложится на ваши нужды.
Ответ написан
@anlamas
Ты связал модели правильно.
Дополнительные данные сводной таблицы будут в pivot.

Нет никакой проблемы достучаться до этих данных:
// Условимся, что settings не пустой
$user->settings[0]->pivot->value

// Можешь переименовать
$this->belongsToMany(RoleSettings::class,'users_settings','user_id','setting_id')
->withPivot('value')
->as('info');
// После писать так
$user->settings[0]->info->value

В общем, у тебя все ок.
<a href="https://laravel.com/docs/8.x/eloquent-relationships#many-to-many">Many to many</a>
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы