【问题标题】:Laravel Pivot table with two relationships to the same model not working as expectedLaravel Pivot 表与同一个模型有两个关系没有按预期工作
【发布时间】:2020-06-25 21:00:32
【问题描述】:

我正在运行一个 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) 的所有播放列表,但是当我转到我的播放列表以查看所有用户时($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 列表(即 user_id = 3)”,但它还添加了“user_id = 1”,这是播放列表的“所有者”的用户 ID


有没有人遇到过在与同一模型有 2 个关系的模型上设置 belongsToMany 关系的经历?

任何建议将不胜感激!我想我已经做了尽可能多的搜索和测试!

谢谢!

【问题讨论】:

  • 我发现真正奇怪的其他事情是:``` public test_function a_user_can_have_invites() { $user = factory(User::class)->create(); //$this->assertCount(0, $user->invites); create(); $playlist->invites()->attach($user); $this->assertCount(1, $playlist->invites); $this->assertCount(1, $user->invites); } ``` 如果我检查一个空集合,它会导致较低的断言失败。如果我将它注释掉,它会起作用!?!?!哇!??!

标签: php laravel pivot-table


【解决方案1】:

您正面临错误,因为您在 playlistsplaylist_user 表中都有 user_id 列,因此您必须提及从哪个表中选择该列,例如 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();
}

【讨论】:

  • 感谢您的反馈,但我认为情况并非如此。从理论上讲,我已经在用户模型中,所以 $this->instances 不应该已经被限定为该用户吗?当我执行where 条件时,它基于播放列表 ID,而不是用户 ID 但我还修改了包含 return $this->invites()->where(['playlist_id' => $playlist_id, 'playlist_user.user_id' => $this->id])->exists(); 的位置,但 user_id 再次出现由于某种原因,Laravel 正在处理 user_id 范围所有者的播放列表,而不是数据透视表
  • 我已经编辑了答案,请检查。我相信Playlist 模型中的invites() 方法会导致错误。尝试像示例中所示修复它
猜你喜欢
  • 1970-01-01
  • 2018-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-06
  • 2014-09-21
相关资源
最近更新 更多