Laravel多对多关系加入两个模型

时间:2017-05-10 12:27:45

标签: php laravel-5

我很难用Laravel 5做到这一点。但是,在Rails中,我可以很容易地做到这一点:

用户可以是许多团队的一部分。我们知道表UserTeam没有关系ID,所以我不会在这里发布这些模式,而是我有一个TeamUser表:

Schema::create('team_users', function (Blueprint $table) {
    $table->increments('id');
    $table->integer('user_id');
    $table->integer('team_id');
    $table->timestamps();
});

TeamUser.php:

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

public function team()
{
  return $this->belongsTo(Team::class);
}

Team.php

public function users()
{
  return $this->hasManyThrough(User::class, TeamUser::class);
}

user.php的

public function teams()
{
  return $this->hasManyThrough(Team::class, TeamUser::class);
}

好像laravel的doc和我见过的其他教程是不同的。我是Laravel的新手,我需要这个设置。

廷克:

$tu = App\TeamUser::create([ 'user_id' => 1, 'team_id' => 1 ]);
  

Illuminate \ Database \ Eloquent \ MassAssignmentException,带有消息' user_id'

预期:

$tu->users // is_array($tu) to be true

有人可以解释一下这里有什么问题吗?非常感谢。

4 个答案:

答案 0 :(得分:1)

据我所知,hasManyThrough()仅代替链接2 hasMany关系。在您的情况下,我们必须处理单个many-to-many关系,该关系是通过在所涉及的两个模型上使用belongsToMany()来定义的。

为此,您应该创建一个连接表。在Laravel中,连接表的命名约定是涉及的两个模型的名称,单数, snake_cased ,并按字母顺序排列,并以_分隔。在这种情况下,表名称为team_user

您需要通过工匠CLI创建迁移:

$ php artisan make:migration create_team_user_pivot_table

并将以下内容放在up()中为您创建的新类的down()YOUR_PROJECT/database/migrations/方法中。

/**
 * Run the migrations.
 *
 * @return void
 */
public function up()
{
    Schema::create('team_user', function (Blueprint $table) {
        $table->integer('team_id')->unsigned()->index();
        $table->foreign('team_id')->references('id')->on('teams')->onDelete('cascade');
        $table->integer('user_id')->unsigned()->index();
        $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
        $table->primary(['team_id', 'user_id']);
    });
}

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

完成所有设置后,您可以使用以下控制台命令运行新迁移: $ php artisan migrate

然后,在您的Team模型中:

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

并在您的User模型中:

public function teams()
{
    return $this->belongsToMany(Team::class);
}

这应该是让关系运作所需的一切。

请注意,没有什么可以阻止您创建名为TeamUser的额外模型来直接访问您的数据透视/联接表。您必须将该模型中的表名指定为team_user,因为Eloquent假定表名为模型名称的多个蛇形版本:team_users。这很简单:

protected $table = 'team_user';

但是,如果额外表的唯一目的是存储关系,我不明白为什么为该表定义Model类可以被认为是有用的。 Laravel附带a bunch of extra features that let you define and access additional columns on join tables through relationships.

(向下滚动一点在数据透视表上保存其他数据

答案 1 :(得分:0)

为避免看到粘贴的错误消息,您必须将以下行添加到TeamUser.php类中:

protected $fillable = ['user_id', 'team_id'];

答案 2 :(得分:0)

您可以使用belongsToMany

实现与中间表的多对多关系

例如在 Team.php

public function users() {
    return $this->belongsToMany(User::class, 'team_user', 'team_id', 'user_id');
}

在这种情况下,您不需要创建模型 TeamUser

答案 3 :(得分:0)

在解决雄辩关系时我所做的就是大声说出来:

  • 用户可以成为许多团队的一员
  • 团队可以拥有多个用户

这表示您需要many-to-many关系。那么,我们在User.php中做了什么:

public function teams() {
    return $this->belongsToMany(Team::class);
}

然后,在我们Team.php中,我们这样做;

public function users() {
    return $this->hasMany(Users::class);
}

这应该会自动生成一个数据透视表,并将您设置为可以请求的位置,例如用户团队:Users::find(1)->teams请注意,我没有使用括号,因为我想要结果,而不是查询构建器对象。