Как искать в сводной таблице строки, которые принадлежат двум пользователям - PullRequest
0 голосов
/ 04 марта 2020

Извините, если это глупый вопрос, но я новичок в Laravel.

У меня есть две модели и сводная таблица:

Пользователь

id | name | password

public function conversations(): ?BelongsToMany
{
  return $this->belongsToMany(Conversation::class)->withTimestamps();
}

Диалог

id

public function users(): ?BelongsToMany
{
  return $this->belongsToMany(User::class)->withTimestamps();
}

разговор_пользователя

id | conversation_id | user_id

Я создаю разговор и назначьте пользователей с syn c следующим образом:

$user->conversations()->syncWithoutDetaching($conversation);
$targetUser->conversations()->syncWithoutDetaching($conversation);

У пользователей может быть много разговоров, и у разговоров может быть несколько пользователей. Это нормально, но когда я хочу поговорить с двумя указанными c пользователями, я не знаю лучшего способа использовать ORM, чтобы найти разговор, от которого они оба отличаются.

Я в настоящее время используется следующий метод, который работает, но кажется, что есть гораздо лучший способ сделать что-то, используя ORM:

/**
 * Get a conversation by a target user id.
 *
 * @param int $targetUserId
 * @return mixed
 */
public function getConversationByTargetUserId(int $targetUserId)
{
    // Get the current user.
    $user = Auth::guard()->user();

    // Check the user exists.
    if (!$user) {
        throw new HttpException(500);
    }

    /**
     * Get all pivot tables where the
     * user ID is from the current user.
     */
    $userConversationIdsArray = DB::table('conversation_user')->where('user_id', $user->id)->pluck('conversation_id');

    /**
     * Get all pivot tables where the user
     * id is equal to the target id, and is
     * also owned by the current user. Return
     * the first instance that we come across.
     */
    $targetConversation = DB::table('conversation_user')->where(['conversation_id' => $userConversationIdsArray, 'user_id' => $targetUserId])->first();

    /**
     * Return the conversation.
     */
    return Conversation::find($targetConversation->conversation_id);
}

Спасибо за ваше время:)

Ответы [ 2 ]

1 голос
/ 04 марта 2020

Есть ли конкретная причина, по которой вы не используете Eloquent? Это может сделать это проще.

Это можно сделать так, как у вас уже есть пользователь.

$user->conversations()->has('users.id', '=', $targetUserId)->first();

(Я не тестировал это решение, поэтому я не уверен, что это работает на 100% )

Также в вашем первом запросе может быть опечатка. Возможно, ошибка копирования вставки может быть опечаткой. Просто проверяю.

$userConversationIdsArray = DB::table('conversation_user')->where('user_id', $user->id)->pluck('id'); <---- 'id' shouldn't that be 'conversation_id'?
0 голосов
/ 04 марта 2020

Благодаря @Fjarlaegur они поставили меня на правильный путь. Работает следующий метод:

/**
 * Get a conversation by a target user id.
 *
 * @param int $targetUserId
 * @return mixed
 */
public function getConversationByTargetUserId(int $targetUserId)
{
    // Get the current user.
    $user = Auth::guard()->user();

    // Check the user exists.
    if (!$user) {
        throw new HttpException(500);
    }

    return $user->conversations()->whereHas('users', function ($query) use ($targetUserId) {
        $query->where('users.id', $targetUserId);
    })->first();
}
...