Laravel自定义枢轴使用(扩展模型或扩展枢轴)

时间:2022-09-15 20:50:40

I am really stuck using a custom model for my pivot, and don't understand why can we make a custom model for it if we can't use it as a model. I've seen many answers and articles, and all chose to extend Pivot or Model, but real life usage is never taken into account and never go any further than giving it a "named" class.

我真的不习惯使用我的支点的自定义模型,并且不明白为什么我们可以为它制作自定义模型,如果我们不能将它用作模型。我已经看过很多答案和文章,所有人都选择扩展Pivot或Model,但是现实生活中的使用从未被考虑过,而且从来没有比给它一个“命名”类更进一步。

Here is an example of what I'm trying to achieve: My main models: Player model, with players table. Game model, with games table.

这是我想要实现的一个例子:我的主要模型:玩家模型,玩家表。游戏模型,带游戏桌。

Player and Game have a many-to-many relationship, that we can call "Party" with a "game_player" table.

玩家和游戏有多对多的关系,我们可以用“game_player”表称为“Party”。

Less important for now, I have also a Score model that holds the score/turns, a Party can have many scores, so scores table has a party_id entry.

现在不太重要的是,我还有一个持有得分/转弯的分数模型,一个Party可以有很多分数,因此分数表有一个party_id条目。

So, here are basically my classes (Laravel 5.2):

所以,这里基本上是我的课程(Laravel 5.2):

Player

class Player extends Model
{
    // The Games this Player is participating to.
    public function games() {
        return $this->belongsToMany(Game::class)->withPivot('id')->withTimestamps();
    }

    // The Scores belonging to this Player.
    public function parties() {
        return $this->hasManyThrough(Score::class, Party::class);
    }

    // The Custom Pivot (Party) creation for this Player.
    public function newPivot(Model $parent, array $attributes, $table, $exists) {
        if ($parent instanceof Game) {
            return new Party($parent, $attributes, $table, $exists);
        }
        return parent::newPivot($parent, $attributes, $table, $exists);
    }
}

Game

class Game extends Model
{
    // The Players participating into this Game.
    public function players() {
        return $this->belongsToMany(Player::class)->withPivot('id')->withTimestamps();
    }

    // The Scores belonging to this Party.
    public function parties() {
        return $this->hasManyThrough(Score::class, Party::class);
    }

    // The Custom Pivot (Party) creation for this Game.
    public function newPivot(Model $parent, array $attributes, $table, $exists) {
        if ($parent instanceof Player) {
            return new Party($parent, $attributes, $table, $exists);
        }
        return parent::newPivot($parent, $attributes, $table, $exists);
    }
}

Party

class Party extends Pivot
{
    protected $table = 'game_player';

    // The Player this Party belongs to.
    public function player() {
        return $this->belongsTo(Player::class);
    }

    // The Game this Party belongs to.
    public function event() {
        return $this->belongsTo(Game::class);
    }

    // The Scores belonging to this Party.
    public function scores()
    {
        return $this->hasMany(Score::class);
    }
}

Score

class Score extends Model
{
    // The Party this Score belongs to (has "party_id" column).
    public function party() {
        return $this->belongsTo(Party::class);
    }
}

Now, I have two different sets of problems that appear depending on if I extend Model or Pivot on Party:

现在,我有两组不同的问题出现,具体取决于我是否扩展了Party上的Model或Pivot:

1) When Party extends Pivot:

1)当Party扩展Pivot时:

  • Can't do something like Party::count(), anything that works with models.
  • 不能做像Party :: count(),任何与模型一起使用的东西。

  • Can't do something like Party::where("player_id", $player->id) and so on ... Basically I want the party to have a scores/turns table attached to it and to do so I need to select the pivot model.
  • 不能做像Party :: where(“player_id”,$ player-> id)等等...基本上我希望派对上有一个得分/转牌表,这样做我需要选择枢轴模型。

  • Can't do something like $events->player->first()->scores() nor event $events->player->first()->pivot->scores(), it breaks with the following:
  • 无法执行类似$ events-> player-> first() - > scores()或事件$ events-> player-> first() - > pivot-> scores(),它会突破以下内容:

PHP error: Argument 1 passed to Illuminate\Database\Eloquent\Relations\Pivot::__construct() must be an instance of Illuminate\Database\Eloquent\Model

PHP错误:传递给Illuminate \ Database \ Eloquent \ Relations \ Pivot :: __ construct()的参数1必须是Illuminate \ Database \ Eloquent \ Model的一个实例

2) When Party extends Model:

2)当Party扩展模型时:

  • Can do trivial things such as Party::count(), Party::where("Game_id", $game->id)
  • 可以做一些琐碎的事情,比如Party :: count(),Party :: where(“Game_id”,$ game-> id)

  • Lose all pivot functions, so can't do $game->players, not even $game->players() work: $game->players()->count() is correct, but $game->players()->first() or $game->players->first() will break with the following:
  • 失去所有的枢轴功能,所以不能做$ game->玩家,甚至不是$ game-> players()工作:$ game-> players() - > count()是正确的,但$ game-> players() - > first()或$ game-> players-> first()将破坏以下内容:

PHP error: Argument 1 passed to Illuminate\Database\Eloquent\Model::__construct() must be of the type array, object given

PHP错误:参数1传递给Illuminate \ Database \ Eloquent \ Model :: __ construct()必须是类型数组,给定对象

Question:

How to correctly use the custom pivot model when instantiating them is different?

在实例化它们时如何正确使用自定义枢轴模型是不同的?

I hope to achieve the following:

我希望实现以下目标:

  • Do the normal $events->players->attach($player)
  • 做正常的$ events-> players-> attach($ player)

  • Be able to attach a score like $score->party_id = $events->players->find($x)->pivot->id (or any other way via a scope for example)
  • 能够附加分数,如$ score-> party_id = $ events-> players-> find($ x) - > pivot-> id(或通过范围的任何其他方式)

  • Be able to count all parties being played, or the ones on one specific game or by a specific player (something like Party::count(), $player->parties->count() etc)
  • 能够计算正在玩的所有方,或特定游戏或特定玩家的方(如Party :: count(),$ player-> parties-> count()等)

Thank you.

1 个解决方案

#1


0  

For my -little- experience with laravel i've found that pivot tables are used when you have a many-to-many relatinship that only keeps one link between a specific object from the table A to the table B. For example User with Role.

对于我对laravel的一点体验,我发现当你有多对多的关系时只使用表A中的特定对象与表B之间保持一个链接,就会使用数据透视表。例如,带角色的用户。

As you can image, a user A just need one link/relation with the role B. But what happens if we want to use a pivot table (for example Sales) that needs to keep different records between userA and productB? I haven't found a direct way to do this.

由于您可以成像,因此用户A只需要与角色B建立一个链接/关系。但是,如果我们想要使用需要在userA和productB之间保留不同记录的数据透视表(例如Sales),会发生什么?我没有找到直接的方法来做到这一点。

My solution is treat the intermadiate table as an actual model, then make one-to-many relationships with both tables (users-sales and products-sales) and then if, I need to, relate this middle model with another ones.

我的解决方案是将intermadiate表视为实际模型,然后与两个表(用户 - 销售和产品 - 销售)建立一对多关系,然后如果我需要将此中间模型与另一个模型相关联。

So in your case, i'd have 4 clear models:

所以在你的情况下,我有4个明确的模型:

  • Player | one-to-many with Party
  • 播放器|与党一对多

  • Game | one-to-many with Party
  • 游戏|与党一对多

  • Party | one-to-one with Score | many-to-one with Party | many-to-one with Player
  • 派对|与分数一对一|与党多对一|与玩家多对一

  • Score | one-to-one with Party
  • 得分|与党一对一

With this approach you also has more control of the properties of each model.

使用这种方法,您还可以更好地控制每个模型的属性。

#1


0  

For my -little- experience with laravel i've found that pivot tables are used when you have a many-to-many relatinship that only keeps one link between a specific object from the table A to the table B. For example User with Role.

对于我对laravel的一点体验,我发现当你有多对多的关系时只使用表A中的特定对象与表B之间保持一个链接,就会使用数据透视表。例如,带角色的用户。

As you can image, a user A just need one link/relation with the role B. But what happens if we want to use a pivot table (for example Sales) that needs to keep different records between userA and productB? I haven't found a direct way to do this.

由于您可以成像,因此用户A只需要与角色B建立一个链接/关系。但是,如果我们想要使用需要在userA和productB之间保留不同记录的数据透视表(例如Sales),会发生什么?我没有找到直接的方法来做到这一点。

My solution is treat the intermadiate table as an actual model, then make one-to-many relationships with both tables (users-sales and products-sales) and then if, I need to, relate this middle model with another ones.

我的解决方案是将intermadiate表视为实际模型,然后与两个表(用户 - 销售和产品 - 销售)建立一对多关系,然后如果我需要将此中间模型与另一个模型相关联。

So in your case, i'd have 4 clear models:

所以在你的情况下,我有4个明确的模型:

  • Player | one-to-many with Party
  • 播放器|与党一对多

  • Game | one-to-many with Party
  • 游戏|与党一对多

  • Party | one-to-one with Score | many-to-one with Party | many-to-one with Player
  • 派对|与分数一对一|与党多对一|与玩家多对一

  • Score | one-to-one with Party
  • 得分|与党一对一

With this approach you also has more control of the properties of each model.

使用这种方法,您还可以更好地控制每个模型的属性。