Laravel得到关系,基于中间人的远距离关系

时间:2015-01-16 14:59:11

标签: php laravel

情景

一个订单可以有多个订单行。每个订单行都可以有很多产品。然后,每个产品都可以分配一个许可证(但仅在订单完成后)。许可证将分配给单个用户。为了澄清,从技术上讲,每个订单行可以有一个或多个产品,并且没有,每个产品的一个或多个许可证。

模型

  • OrderHeader(id,status,currency,...)
  • OrderLine(id,order_header_id,total,....)
  • 产品(id,name,parent_id)
  • 许可证(id,user_id,product_id,order_line_id)
  • 用户(身份证,姓名,电子邮件,......)

还有一个order_line_product表,其中包含order_line_id和product_id字段。

因此,订单包含OrderHeader表中的记录,其中包含OrderLine表中的许多记录,这些记录通过order_line_product表链接到Product。许可证是单独添加的,但具有引用用户和OrderLine的相关字段。

要求

我想以下列格式输出日期:

OrderHeader
 - OrderLine 1
   - Product 1
     - Licence 1
       - User 1
     - Licence 2
       - User 2
   - Product 2
      - Licence 3
        - User 3
 - OrderLine 2
   - Product 1
 - OrderLine 3
   - Product 1
   - Product 2
     - Licence 4
        - User 4
   - Product 3

关键是我想以这种方式返回一个正确加载关系的Collection。

模型中的关系代码

OrderHeader

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

订单行

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

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

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

产品

public function orderLine()
{
    return Product::belongsToMany('App\OrderLine');
}

public function licence()
{
    return Product::belongsToMany('App\Licence');
}

许可证

public function user()
{
    return Licence::belongsTo('App\User');
}

public function line()
{
    return Licence::belongsTo('App\OrderLine', 'order_line_id');
}

public function product()
{
    return Licence::hasOne('App\Product', 'id', 'product_id');
}

希望所有人都按预期流动。

当前代码

如果我使用:

$order = OrderHeader::findOrFail($id)->load('lines.products', 'lines.licences.user', 'creator');

它非常接近我想要的输出,所有正确的数据都存在,但是'许可证'关系不是嵌套在'产品中?关系。如果我输出数据,它将采用以下格式:

OrderHeader
 - OrderLines
   - Products
      - Product 1
      - Product 2
      - etc...
   - Licences
      - Licence 1
        - User
      - Licence 2
        - User
      - etc...

即。许可证与产品处于同一级别,而不是嵌套在其中。

我想要的是:

OrderHeader
 - OrderLines
   - Products
     - Product 1
       - Licences
         - Licence 1
           - User

这将使我能够非常轻松地遍历订单的完整层次结构,而无需进行凌乱的foreach / if check。

谢谢!

2 个答案:

答案 0 :(得分:1)

尝试以下方法;

$order = OrderHeader::findOrFail($id)->load('lines.products', 'lines.products.licence','lines.products.licence.user', 'creator');

当您从线路加载许可证而不是产品本身时。然后在其上添加用户应该为您提供所需的数据结构。

答案 1 :(得分:0)

当您在产品上说出需要时,您正在为用户加载许可证。试试这个。

$order = OrderHeader::findOrFail($id)->load('lines.products.licence.user');

我也感觉您的关系错误地使用belongsToMany(),因为我没有看到任何数据透视表,但是如果没有看到您的架构,我无法确定。根据您所拥有的内容,您应该使用belongsTo()hasOne()hasMany()