Laravel数据透视表和模型事件

时间:2014-06-04 12:00:23

标签: php laravel laravel-4 eloquent

我正在开发一款游戏,我目前正在管理部分添加游戏和关卡。

我通过带有" order"的数据透视表引用游戏和关卡。列。

我的游戏模型:

class Game extends Eloquent {

    public function levels() {
        return $this->belongsToMany('Level')->withPivot('order');
    }
}

我的等级模型:

class Level extends Eloquent {

    public function game() {
        return $this->belongsToMany('Game')->withPivot('order');
    }
}

我想要实现的是在添加关卡时自动填充订单列,并创建moveup()和movedown()函数。

我尝试在关卡模型上设置一个模型事件来实现这一目标但是没有成功。

1 个答案:

答案 0 :(得分:4)

首先,这种秩序是单向的。你不能在游戏的关卡顺序中使用相同的列,反之亦然。

现在,您可以通过覆盖关系上的attach方法来检查当前最大位置并相应地为插入添加next(不创建事件或任何事情,因为这与{无关),从而实现您所需的功能。 {1}}创造本身,而不是将其附加到游戏中。)

话虽如此,您需要扩展Eloquent level或使用特征才能使用自定义Model关系。像下面这样的东西应该做的工作(没有评论等,使其可能简洁)。

BelongsToMany

// Game model
class Game extends Eloquent {

  use SortablePivotModelTrait;

  public function levels()
  {
    return $this->sortableBelongsToMany('Level', 'order')->withPivot('order');
  }

  //...
}

// SortablePivotModelTrait.php
use Illuminate\Database\Eloquent\Model;

trait SortablePivotModelTrait {

    public function sortableBelongsToMany($related, $orderColumn = null, $table = null, $foreignKey = null, $otherKey = null, $relation = null)
    {
        // all the code of belongsToMany method needs to go here
        // ...

        // then just:
        return new SortableBelongsToMany($query, $this, $table, $foreignKey, $otherKey, $relation, $orderColumn);
    }

}

这样你可以这样做:

// SortableBelongsToMany.php
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;

class SortableBelongsToMany extends BelongsToMany {

    protected $orderColumn;

    public function __construct(Builder $query, Model $parent, $table, $foreignKey, $otherKey, $relationName = null, $orderColumn = 'order')
    {
        $this->orderColumn = $orderColumn;

        parent::__construct($query, $parent, $table, $foreignKey, $otherKey, $relationName);
    }

    public function attach($id, array $attributes = array(), $touch = true)
    {
        $attributes = array_merge($attributes, [$this->getOrderColumnName() => $this->getNextPosition()]);

        return parent::attach($id, $attributes, $touch);
    }

    public function getNextPosition()
    {
        return 1 + $this->newPivotQuery()->max($this->getOrderColumnName());
    }

    public function getOrderColumnName()
    {
        return $this->orderColumn;
    }

}