Laravel Сводная таблица с двумя отношениями к одной и той же модели не работает должным образом - PullRequest
2 голосов
/ 14 марта 2020

Я запускаю приложение Laravel 7, и у меня есть 2 модели относительно друг друга. Модель User и Playlist.

....
App\Playlist

public function user()
{
     return $this->belongsTo(User::class);
}
....

, которая работает правильно, и, конечно, моя Playlist миграция имеет внешний ключ на user_id

Теперь я Я пытаюсь создать сценарий, в котором есть сводная таблица, которая позволяет другим пользователям «приглашаться» в плейлист. В этом сценарии я хочу иметь доступ ко всем плейлистам, которые пользователь «пригласил», а в плейлисте я хочу видеть всех пользователей, которые были приглашены в плейлист.

Я создал сводную таблицу с использованием стандартных Laravel лучших практик

class CreatePlaylistUserTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('playlist_user', function (Blueprint $table) {
            $table->id();
            $table->unsignedBigInteger('playlist_id');
            $table->foreign('playlist_id')->references('id')->on('playlists')->onDelete('cascade');

            $table->unsignedBigInteger('user_id');
            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');

            $table->unique(['playlist_id', 'user_id']);

            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('playlist_user');
    }
}

В модели моего пользователя у меня есть belongsToMany отношение

App\User

    /**
     * The Playlists associated with the user.
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function playlists()
    {
        return $this->hasMany(Playlist::class);
    }

    /**
     * The Playlists that this user has been invited to.
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsMany
     */
    public function invites()
    {
        return $this->belongsToMany(Playlist::class)->withTimestamps();
    }

и на моем У меня есть модель списка воспроизведения

App\Playlist

    public function user()
    {
        return $this->belongsTo(User::class);
    }

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

После добавления users к playlists ($playlist->invites()->attach($user)) в моих тестах я могу видеть все списки воспроизведения для своего пользователя ($user->invites), но когда Я go в своем плейлисте, чтобы увидеть всех пользователей ($playlist->invites) Я вижу пустую коллекцию, хотя запись существует в моей БД

Я также проверяю, существует ли запись, выполняя что-то как

App\User

public function isInvitedToPlaylist($playlist) {
    return $this->invites()->where('playlist_id', $playlist->id)->exists();
}

Но я продолжаю получать неоднозначное имя столбца: ошибка user_id

lluminate\Database\QueryException: SQLSTATE[HY000]: General error: 1 ambiguous column name: user_id (SQL: select exists(select * from "playlists" inner join "playlist_user" on "playlists"."id" = "playlist_user"."playlist_id" where "playlist_user"."user_id" = 3 and "playlist_id" = 1 and "user_id" = 1) as "exists")

В моей голове я запрашиваю список воспроизведения playlistUser (ie. user_id = 3 ) ", но он также добавляет в" user_id = 1 ", который является идентификатором пользователя 'владельца' для списка воспроизведения


Кто-нибудь испытывал настройку отношения belongsToMany на модели, которая имеет 2 отношения к одной модели?

Любой совет будет оценен! Я думаю, что сделал как можно больше поиска и тестирования!

Спасибо!

1 Ответ

0 голосов
/ 14 марта 2020

Вы столкнулись с ошибкой, поскольку у вас есть столбец user_id в таблицах playlists и playlist_user, поэтому вы должны указать, из какой таблицы выбрать этот столбец, например where('playlists.user_id', $id)

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

// Playlist model
public function invites()
{
    return $this->belongsToMany(User::class)
                ->select([
                    'playlist.id',
                    'playlist.user_id',
                     ...
                    'playlist_user.id',
                    'playlist_user.user_id',
                    'playlist_user.playlist_id',
                     ...
                    'users.id',
                    'users.other_column'
                ])
                ->withTimestamps();
}
...