在laravel中的嵌套预先加载中加载特定关系

时间:2018-02-23 16:18:40

标签: php laravel eloquent laravel-5.5 laravel-eloquent

我有以下相关表格:

tableA 
  - id 
  - value

tableB 
  - id 
  - tableA_id
  - value

tableC 
  - id 
  - tableB_id
  - value


tableD 
  - id 
  - tableC_id
  - value

我通常使用嵌套的预先加载来从tableD获取tableaA的对象,例如:

$table_d = TableD::with('TableC.TableB.TableA')->find($id);

我得到一个这样的对象:

{
    "id": 1,
    "value": "value",
    "tableC_id": 1,
    "tablec": {
                "id": 1,
                "value": "value",
                "tableB_id": 1,
                "tableb": {
                            "id": 1,
                            "value": "value",
                            "tableA_id": 1,
                            "tablea": {
                                        "id": 1,
                                        "value": "value"
                            }
                }
    }
}

我想要实现的只是获取表D的对象,其对象来自表A,而最终对象中没有表C和表B,如下所示:

{
    "id": 1,
    "value": "value",
    "tablea": {
                "id": 1,
                "value": "value"
                }
    }
}

我尝试在表D的模型文件中添加此函数:

public function TableA()
    {
        return $this->belongsTo('App\Models\TableC', 'tableC_id')
                                ->join('tableB','tableC.tableB_id','=','tableB.id')
                                ->join('tableA','tableB.tableA_id','=','tableA.id')
                                ->select('tableA.id', 'tableA.value');
    }

但它不起作用,因为当我执行以下查询时,它返回一些好的对象,其他的返回tableA = null:

$tables_d = TableD::with('TableA')->get()

我做错了什么或者有其他方法可以达到我的目的吗?

3 个答案:

答案 0 :(得分:2)

你可以跳过一张桌子 this->hasManyThrough()但是根据您真正想要的未来功能,您可能希望根据需要与您想要的任何代码建立多种关系。 QueryScopes以及。

答案 1 :(得分:1)

当它只是两个表和一个链接表之间时,通常可以使用一个有很多通过关系来映射表。除此之外,你还有另一个联盟,所以它不会比现在的好得多。

您是否考虑过直接从D到A的另一个映射表或一些非规范化?如果您总是需要加载它,那么您可能会因为有一些重复的fks来节省连接而受益。

这实际上取决于你的需求,它不是3NF(第三范式),也许它甚至不是2NF,但这就是为什么非规范化就像逗号一样使用...一般遵循规则但出于特定原因打破它们;在这种情况下,通过复制表中的FK引用来减少所需的连接数。

https://laravel.com/docs/5.6/eloquent-relationships#has-many-through

答案 2 :(得分:0)

您可以尝试这样做:   - 在TableD Model中添加一个方法:

public function table_a()
{
    return $this->TableC->TableB->TableA();
}

然后使用:TableD::with(table_a);