【问题标题】:Laravel 5.2 Eloquent - Model through Many-To-Many RelationshipLaravel 5.2 Eloquent - 通过多对多关系建模
【发布时间】:2016-12-20 23:27:06
【问题描述】:

我有 3 个模型:环境、站点和事件。每个都有各自的表格。

我的模型关系定义如下:

环境有很多站点(站点表中的environment_id

public function sites()
{ 
   return $this->hasMany('App\Site');
}

站点属于一个环境(站点表中的environment_id)并属于许多事件(带有incident_idsite_id 的incident_site 关系表)

public function environment()
{
    return $this->belongsTo('App\Environment');
}

public function incidents()
{
    return $this->belongsToMany('App\Incident');
}

事件属于多个站点(incident_site 关系表与incident_idsite_id

public function sites()
{
    return $this->belongsToMany('App\Site');
}

问题:我正在尝试通过这样的环境模型检索所有站点事件的集合:

$environment->incidents()->count();

到目前为止,我能够让它在控制器中工作的唯一方法是这样的:

    $environment->load(['sites.incidents' => function ($q) use ( &$incidents ) {
       $incidents = $q->orderBy('id','desc')->get();
    }]);

但在应用程序的其他区域使用它并不理想。

问题:如何通过环境模型中的方法使上述关系发挥作用?有没有更简单的方法?

【问题讨论】:

  • 其实没有hasManyThrough()这种关系的方法,不过你可以使用下面的答案来获取功能。

标签: laravel eloquent many-to-many


【解决方案1】:

没有任何规定可以在多对多关系中使用hasManyThrough()。但是您可以通过使用DB::raw() 来实现这一点,或者您可以按照forum 中给出的那样将以下函数添加到您的BaseModel。

public function manyThroughMany($related, $through, $firstKey, $secondKey, $pivotKey)
   {
       $model = new $related;
       $table = $model->getTable();
       $throughModel = new $through;
       $pivot = $throughModel->getTable();

       return $model
           ->join($pivot, $pivot . '.' . $pivotKey, '=', $table . '.' . $secondKey)
           ->select($table . '.*')
           ->where($pivot . '.' . $firstKey, '=', $this->id);
   }

更新:使用

首先你需要为incident_site创建一个模型

class incident_site extends Model{
    public $table = 'incident_site';
    //your other code
}

在您的 Enviorment 模型中添加 Incidents() 方法:

public function Incidents()
    {
        return $this->manyThroughMany('App\Incident', 'App\incident_site', 'site_id', 'id', 'incident_id');
}

更新:

已根据您的需要修改了功能。
将您的功能更改为以下内容:

public function manyThroughMany($related, $through ,$middle , $firstKey, $secondKey, $pivotKey)
    {
        $model = new $related;
        $table = $model->getTable();
        $throughModel = new $through;
        $pivot = $throughModel->getTable();
        $middleModel = new $middle;
        $middleModelIds = $middleModel->where($this->getForeignKey(),$this->getKey())->get()->lists('id')->toArray();
        //$middleModelIds = $this->with($middleModel)->where()->get()->lists('id')->toArray();
        //$middleModelIds = $this->sites()->get()->lists('id')->toArray();
        return $model
            ->join($pivot, $pivot . '.' . $pivotKey, '=', $table . '.' . $secondKey)
            ->select($table . '.*')
            ->whereIn($pivot . '.' . $firstKey,$middleModelIds);// '=', $this->id);
    }

使用:
需要传递中间表的额外参数。

public function Incidents()
    {
        return $this->manyThroughMany('App\Incident', 'App\incident_site','App\Site','site_id', 'id', 'incident_id');
    }

【讨论】:

  • 谢谢。我已经扩展了基本模型,可以使用您提供的功能。我不断收到未找到列的错误。如果我在 Environment 模型中添加 events() 关系,正确的参数是什么?
  • 刚刚再次测试。它似乎收集了与每个环境仅 1 个站点相关的事件集合。有些环境有很多站点。
  • @kayex 更新我的答案。如果可行,我想获得我的“摇滚明星”学位:P
  • 哈哈!你肯定获得了摇滚明星学位。这现在完美无缺。再次感谢您对此的帮助。
猜你喜欢
  • 2019-06-13
  • 2020-03-04
  • 2019-12-22
  • 2019-01-21
  • 2015-11-10
  • 2019-03-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多