Laravel关系:一个foreignKey对几个localKey关系



我必须用Laravel开发一个api,但我遇到了这个问题:我需要得到所有的匹配,对于每一个匹配,我需要得到属于这个匹配的用户(每个匹配有2个用户)

我已经搜索了这个问题的答案,我找到了这个https://github.com/topclaudy/compoships但它对我不起作用。

到目前为止,我有这个:

class Match extends Model
{
protected $table = 'matchs';
public $primaryKey = 'id';
public function playerOne() {
return $this->hasMany('AppUser', 'id', 'playerOne_id');
}
public function playerTwo() {
return $this->hasMany('AppUser', 'id', 'playerTwo_id');
}
}

控制器方法:

public function index()
{
$matchs = Match::with('playerOne', 'playerTwo')->orderBy('created_at', 'asc')->get();
return $matchs; 
//return new MatchsCollection($matchs);
}

我的数据库如下所示:(Matchs表)

id    | playerOne_id   | playertwo_id | winner_id | status 
------------------------------------------------------------
1     | 1              | 3            | 0         | PENDING
2     | 2              | 1            | 0         | PENDING
3     | 3              | 2            | 0         | PENDING

和用户表:

id    | name      | email           
-----------------------------------
1     | John      | John@email.com 
2     | Mark      | Mark@email.com
3     | Harry     | Harry@email.com

当我调用我的api时,我得到的结果是:

[
{
id: 1,
playerOne_id: 1,
playerTwo_id: 3,
winner_id: 0,
status: "PENDING",
created_at: "2019-01-10 00:00:00",
updated_at: null,
users: [
{
id: 1,
name: "John",
email: "John@email.com",
email_verified_at: null,
created_at: "2019-01-11 10:38:26",
updated_at: "2019-01-11 10:38:26"
}
]
},
{
id: 2,
playerOne_id: 2,
playerTwo_id: 1,
winner_id: 0,
status: "PENDING",
created_at: "2019-01-11 08:26:28",
updated_at: "2019-01-11 08:26:28",
users: [
{
id: 2,
name: "Mark",
email: "Mark@email.com",
email_verified_at: null,
created_at: "2019-01-11 10:40:13",
updated_at: "2019-01-11 10:40:13"
}
]
},
{
id: 3,
playerOne_id: 3,
playerTwo_id: 2,
winner_id: 0,
status: "PENDING",
created_at: "2019-01-11 08:45:22",
updated_at: "2019-01-11 08:45:22",
users: [
{
id: 3,
name: "harry",
email: "harry@email.com",
email_verified_at: null,
created_at: "2019-01-11 10:40:13",
updated_at: "2019-01-11 10:40:13"
}
]
}
]

我不想得到的是这个结果(我只是给你看第一场比赛)

[
{
id: 1,
playerOne_id: 1,
playerTwo_id: 3,
winner_id: 0,
status: "PENDING",
created_at: "2019-01-10 00:00:00",
updated_at: null,
users: [
{
id: 1,
name: "John",
email: "John@email.com",
email_verified_at: null,
created_at: "2019-01-11 10:38:26",
updated_at: "2019-01-11 10:38:26"
},
{
id: 3,
name: "Harry",
email: "Harry@email.com",
email_verified_at: null,
created_at: "2019-01-11 10:38:26",
updated_at: "2019-01-11 10:38:26"
}
]
}
]

这在拉腊维尔可能吗?谢谢:)

为了能够将所有玩家作为user数组的一部分返回,您可以将MatchUser之间的关系更改为belongsToMany(多对多),也可以在从控制器返回之前简单地操作匹配数据。

我建议将其更改为BelongsToMany,因为它在语义上更有意义,但我理解(取决于您迄今为止所做的工作)它可能不实用。

您需要:

  1. matchs表重命名为matches(这也意味着您可以从Match模型类中删除
    protected $table = 'matchs';)
  2. 创建一个名为match_user的表。如果您的项目正在使用迁移,那么您可以运行:
    php artisan make:migration create_match_user_table --create=match_user
    在该迁移中,您需要将up()方法的内容更改为:

    public function up()
    {
    Schema::create('match_user', function (Blueprint $table) {
    $table->integer('match_id')->unsigned();
    $table->integer('user_id')->unsigned();
    $table->timestamps();
    $table->primary(['match_id', 'user_id']);
    });
    }
    
  3. 运行php artisan migrate

  4. 在您的Match模型中,将users()关系更改为:

    public function users()
    {
    return $this->belongsToMany(User::class)->withTimestamps();
    }
    
  5. 如果表中的数据是伪数据,则可以跳过此步骤。否则,您需要将playerOne_idplayertwo_id信息移动到新的透视表中。你可以这样做将如下:

    Match::all()->each(function ($match) {
    $match->users()->attach([$match->playerOne_id, $match->playertwo_id]);
    });
    

    你在哪里运行这个并不重要,因为它只需要运行一次,所以运行后你可以删除它。我通常会在路由或修补程序中运行它。

  6. 然后是清理。同样,如果您拥有的数据只是伪数据,那么我只会在原始迁移中删除playerOne_idplayertwo_id,否则创建一个新的迁移,删除那些字段Droping columns docs


完成上述操作后,您只需要在控制器中执行以下操作即可获得结果:

$matches = Match::with('users')->latest()->get();

最新更新