Laravel hasManyThrough审问中间关系以及遥远的中间关系

时间:2015-01-14 17:51:10

标签: php laravel

我想执行以下操作(使用一些相当粗略的伪代码):

SELECT a users orderLines WHERE the orderheader's status ='paid' AND the orderLine's productId>5

换句话说,用户可以下多个订单。每个订单都有一个或多个订单行。我想找到用户已经放置的所有订单行(订单行,而不是订单),但仅当订单头具有特定状态时,并且仅当订单行检查了另一个参数时。这可以是添加行的日期,或者productId是x,依此类推。

使用标准的MySql查询非常简单。

我有必要的模型:

  • 用户
  • OrderHeader(中级关系)
  • OrderLine(远程关系 - 这是我想通过中间人获取的内容)

以下是每种模型中关系的定义方式:

用户

 public function orders()
{
    return $this->hasMany('App\OrderHeader', 'user_id', 'id');
}

public function lines()
{
    return $this->hasManyThrough('\App\OrderLine', 'App\OrderHeader', 'user_id', 'order_header_id');
}

OrderHeader

public function lines()
{
    return $this->hasMany('App\OrderLine', 'order_header_id', 'id');
}

public function user(){
    return $this->belongsTo('User', 'id', 'user_id');
}

OrderLine(使用hasManyThrough为用户获取这些内容)

public function header()
{
    return $this->belongsTo('App\OrderHeader', 'order_header_id');
}

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

所以,我使用:

加载用户
$person = User::findOrFail($id)

然后我可以使用:

$user->lines()->where('product_id','>=',10)->paginate(20); 

因此,它可以很好地获取用户放置的所有行,这些行匹配行记录上的条件。但是,我无法弄清楚如何在中间体上添加第二个条件,这样我不仅可以检查product_id,还可以通过orders()关系查询OrderHeader实体。

我试过了:

return $user->orders()->where('status','=','Paid')->lines()->where('product_id','>=',20))->paginate(20);

但返回错误:调用未定义的方法Illuminate \ Database \ Query \ Builder :: lines()

1 个答案:

答案 0 :(得分:0)

hasManyThrough是Eloquent中的一个特例,其中表是连接的(中间表),所以它非常简单 - 只需查询该表。与其他关系无关。

这就是你想要的:

$throughTable = $user->lines()->getParent()->getTable();

$user->lines()
     ->where('product_id', '>=', 10)
     ->where('orderheaders.status', 'paid')
     // or
     // where("{$throughTable}.status', 'paid')
     ->paginate(20);

顺便说一下,这种关系是错误的:

// OrderHeader model
public function user(){
    return $this->belongsTo('User', 'id', 'user_id'); // wrong keys order
}

// should be
public function user(){
    return $this->belongsTo('User', 'user_id', 'id');
}