简体   繁体   English

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

[英]Load specific relations in a nested eager loading in laravel

I have the following related tables: 我有以下相关表格:

tableA 
  - id 
  - value

tableB 
  - id 
  - tableA_id
  - value

tableC 
  - id 
  - tableB_id
  - value


tableD 
  - id 
  - tableC_id
  - value

I normally use a nested eager loading to get the object of tableaA from tableD, for example: 我通常使用嵌套的eager加载来从tableD获取tableaA的对象,例如:

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

And I get an object like this: 我得到一个像这样的对象:

{
    "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"
                            }
                }
    }
}

What I want to achieve is to obtain only the object of table D, with its object from table A related, without having table C and table B in the final object, something like this: 我想要实现的只是获取表D的对象,其对象来自表A,而最终对象中没有表C和表B,如下所示:

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

I tried adding this function in the model file of Table D: 我尝试在表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');
    }

but it does not work because when I do the following query, it returns some good objects and others with tableA = null: 但它不起作用,因为当我执行以下查询时,它返回一些好的对象,其他的返回tableA = null:

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

Am I doing something wrong or is there another way to achieve what I want? 我做错了什么还是有另一种方式来实现我想要的东西?

You may be able to skip a table with this->hasManyThrough() but depending on what you really want as 'future features', you may want to have multiple relations with whatever code you desire according to your needs. 您可以使用this->hasManyThrough()跳过表格,但根据您真正想要的“未来功能”,您可能希望根据需要与所需的任何代码建立多个关系。 QueryScopes aswell. QueryScopes以及。

One can generally use a has many through relationship for mapping tables when it is just two tables and a linking table between. 当一个表只有两个表和一个链接表时,通常可以使用一个有很多通过关系来映射表。 You have yet another join beyond that so it won't really be much better than what you have currently. 除此之外你还有另一个联盟,所以它不会比你现在的好多少。

Have you considered another mapping table from D to A directly or a bit of denormalization? 您是否考虑过直接从D到A的另一个映射表或一些非规范化? If you always need to load it like that you might benefit from having a bit of duplicated fks to save on the joins. 如果你总是需要加载它,你可能会受益于有一些重复的fks来保存连接。

This will really depend on your needs and it is not 3NF (third normal form), maybe it's not even 2NF, but that's why denormalization is like comma use...follow the rules generally but break them for specific reasons; 这实际上取决于你的需求,它不是3NF(第三范式),也许它甚至不是2NF,但这就是为什么非规范化就像逗号一样使用...一般遵循规则但是出于特定原因而破坏它们; in this case to reduce the number of required joins by duplicating a FK reference in a table. 在这种情况下,通过复制表中的FK引用来减少所需的连接数。

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

You can try to do this: - add a method in TableD Model: 您可以尝试这样做: - 在TableD模型中添加一个方法:

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM