Laravel красноречивый - отношение один к одному с другой таблицей - PullRequest
0 голосов
/ 28 февраля 2020

У меня есть три таблицы,

1. user (id, name)
2. state (id, stateName, code)
3. user_relations(id, user_id, state_id)

3 модели,

1. User
2. State 
3. UserRelation

По логам c, User имеет одну UserRelation и UserRelation имеет один State

Я могу получить пользовательское состояние с помощью

User::first()->relation->state

То, что я хочу , это вызвать User::with('state')->first().

Ответы [ 5 ]

1 голос
/ 28 февраля 2020

Если вы хотите сохранить текущую схему БД такой, какой она есть, вы можете использовать Laravel аксессоры

Аксессоры и мутаторы позволяют форматировать значения атрибутов Eloquent, когда вы извлекаете или устанавливаете их для экземпляров модели.

класс User

public function getStateAttribute($value) {
   return $this->relation->state;
}

Использование

User::findOrFail($id)->state;

Редактировать

Модель пользователя

class User extends Authenticatable
{
    //...

    public function state() {
        return $this->relation()->with('state');
    }


    public function relation() {
        return $this->hasOne('App\UserRelation', 'user_id');
    }

}

Модель UserRelation

class UserRelation extends Model
{
    protected $table = 'user_relations';


    public function state() {

        return $this->belongsTo('App\State'); // must be belongsTo instead of hasOne
    }

}

Модель состояния

class State extends Model
{
    protected $table = 'states';
}

Контроллер

App\User::with('state')->find(1);

{
  "id": 1,
  "name": "Test",
  "email": "test@test.com",
  "email_verified_at": "2020-02-13 00:00:00",
  "created_at": "2020-02-20 00:00:00",
  "updated_at": null,
  "state": {
    "id": 2,
    "state_id": 2,
    "user_id": 1,
    "state": {
      "id": 2,
      "stateName": "state 2",
      "code": "code 2"
    }
  }
}
0 голосов
/ 28 февраля 2020

Так как пользователь и состояние являются многими для многих, вы можете использовать функцию ownToMany внутри модели пользователя.

public function states(){
    return $this->belongsToMany(State::class, 'user_relations', 'user_id', 'state_id');
}

Вы можете получить Жесткая загрузка , получив обе модели, относящиеся к пользователю, например: :

$user = User::with('states')->first();

А теперь, чтобы получить состояния, вы можете l oop через такие состояния, как:

foreach($user->states as $state){
    //Retrieved state model variable
    ....
}
0 голосов
/ 28 февраля 2020

Первый способ:

Вы должны определить state_id в таблице пользователей для отношения один к одному.

class User extends Model
{
    public function state()
    {
        return $this->hasOne('App\State');
    }
}

Или, если вам нужна такая же структура базы данных, тогда

Второй способ:

По сути это Отношение ко многим ко многим между пользователем и государством .

Так что лучше определить функция отношения «многие ко многим» в моделях пользователя и состояния с учетом UserRelation * средняя (сводная) таблица.

class User extends Model
{
    public function states()
    {
        return $this->belongsToMany('App\State', 'user_relations');
    }
}

class State extends Model
{
    public function users()
    {
        return $this->belongsToMany('App\User', 'user_relations');
    }
}

, а затем для доступа к состояниям пользователя вы можете вызвать:

$user->states->first();

Это нормально, что вам нужно отношение один к одному, вы можете вызвать метод first () для получения состояния od первой записи.

Simillery для доступа к пользователю состояния

$state->users->first();

И если вам нужен только user_relations (один к одному), вы должны определить методы как в модели пользователя, так и в модели состояния:

class User extends Model
{
    public function user_relation()
    {
        return $this->hasOne('App\UserRelation');
    }
}

class State extends Model
{
    public function user_relation()
    {
        return $this->hasOne('App\UserRelation');
    }
}
0 голосов
/ 28 февраля 2020

Если у вас есть отношения one-to-one, вам не понадобится сводная таблица, в вашем случае таблица user_relations. Сводные таблицы используются для express many-to-many отношений.

И для решения, которое вы хотите. Вам нужно сохранить user_id в таблице state. поэтому ваша таблица состояний должна выглядеть следующим образом:

state (id, user_id, stateName, code)

Отношения должны быть такими:

Модель пользователя:

public function state()
{
    return $this->hasOne('App\State');
}

Состояние модели:

public function user()
{
    return $this->belongsTo('App\User');
}
0 голосов
/ 28 февраля 2020

Если пользователь может иметь только одно состояние,

добавьте state_id в таблицу пользователей и избавьтесь от третьей таблицы user_relations

class User extends Model
{
    public function state()
    {
        return $this->hasOne('App\State');
    }
}

class State extends Model
{
    public function user()
    {
        return $this->belongsTo('App\User');
    }
}

Таким образом, вы может

$state = User::find(1)->state;
$user = State::find(1)->user;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...