Установить отношения для двух полей, относящихся к одной и той же таблице

#php #laravel #laravel-5 #laravel-5.3

#php #laravel #laravel-5 #laravel-5.3

Вопрос:

У меня есть users таблица со многими пользователями, например:

 id | name
1  | mike
2  | nina
3  | john 
  

У меня также есть posts таблица с a user_id , которая представляет первоначального создателя сообщения, и a locked_user_id , которая заполняется, если сообщение было заблокировано редактором.

Любой пользователь может заблокировать или открыть сообщение, но если сообщение заблокировано, только этот пользователь может его редактировать. Это мои отношения:

Пользовательская модель:

 public function posts(){
    return $this->hasMany('AppPost');
}
  

Модель Post:

 public function user(){
    return $this->belongsTo('AppUser');
}
  

И я могу легко получить автора с помощью

 $posts->user->name
  

Я хотел бы иметь возможность получить как исходного пользователя-создателя, так и редактора. Например, образец таблицы post:

 | id | user_id |    post    | locked_user_id |
| 1  |    1    |  blah blah |       2        |
  

В этом случае $posts->user->name возвращается mike, но я хочу иметь возможность получить пользователя nina, который в данный момент блокирует сообщение.

Как я могу это сделать?

Ответ №1:

Предполагая locked_user_id , что может быть null, и, если это так, возвращаемый пользователь основан на used_id , вы могли бы обновить user() отношение в Post модели до:

 public function user()
{
    if (!is_null($this->locked_user_id)) {
        return $this->belongsTo('AppUser', 'locked_user_id', 'id');
    }

    return $this->belongsTo('AppUser');
}
  

Итак, если locked_user_id возвращаемое используемое основано на этом поле, в противном случае возвращаемый пользователь основан на user_id поле


Согласно комментарию, если вы хотите получить доступ к обоим пользователям, вы можете добавить другое отношение к Post модели. Например

 // Assuming `user_id` is not nullable, this will always return the original user
public function creator()
{
    return $this->belongsTo('AppUser');
}

// Assuming `locked_user_id` is nullable, this will return either `null`, if there is no editor or the user that locked the post
public function editor()
{
    return $this->belongsTo('AppUser', 'locked_user_id', 'id');
}
  

В вашем коде вы можете сделать что-то вроде:

 if (is_null($this->editor)) {
    dd('There is no editor');
} elseif ($this->editor->id === $this->creator->id) {
    dd('The original creator has locked the post');
} else {
    dd('The post was created by ' . $this->creator->name. ' but now is locked by ' . $this->editor->name);
}
  

Комментарии:

1. но идентификатор пользователя всегда является автором. который исправлен для первого парня, который изначально создает сообщение. таким образом, в случае, когда заблокированный пользователь не является исходным пользователем. я хочу, чтобы оба имени были возвращены.

2. @MohamedAthif Вы не можете сделать это с помощью одного отношения. Лучшее решение — иметь два отношения, одно для создателя, а другое для редактора (которое может возвращать значение null).

3. как мне создать два отношения для одного сообщения? отправить сообщение пользователю? разве это не приведет к удвоению?

4. @MohamedAthif обновил ответ как отношениями, так и примером кода. Чтобы ответить на ваш отредактированный комментарий, нет, он не «создает дубликаты». У вас просто есть два поля, относящиеся к одной и той же таблице, следовательно, два отношения.

5. пришлось немного подправить код if 🙂 но отношение работает идеально и выполняет свою работу. Спасибо