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

Rus*_*man 5 php laravel eloquent laravel-eloquent laravel-5.5

我有以下相关表格:

tableA 
  - id 
  - value

tableB 
  - id 
  - tableA_id
  - value

tableC 
  - id 
  - tableB_id
  - value


tableD 
  - id 
  - tableC_id
  - value
Run Code Online (Sandbox Code Playgroud)

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

$table_d = TableD::with('TableC.TableB.TableA')->find($id);
Run Code Online (Sandbox Code Playgroud)

我得到一个像这样的对象:

{
    "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"
                            }
                }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

{
    "id": 1,
    "value": "value",
    "tablea": {
                "id": 1,
                "value": "value"
                }
    }
}
Run Code Online (Sandbox Code Playgroud)

我尝试在表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');
    }
Run Code Online (Sandbox Code Playgroud)

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

$tables_d = TableD::with('TableA')->get()
Run Code Online (Sandbox Code Playgroud)

我做错了什么还是有另一种方式来实现我想要的东西?

And*_*ton 1

当只有两个表和一个链接表之间时,通常可以使用具有多个直通关系的映射表。除此之外,您还有另一个加入,因此它不会比您当前的加入好多少。

您是否考虑过直接从 D 到 A 的另一个映射表或一些非规范化?如果您总是需要像这样加载它,您可能会受益于在连接上保存一些重复的 fks。

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

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