Laravel 8 多表关系

Posted

技术标签:

【中文标题】Laravel 8 多表关系【英文标题】:Laravel 8 Multiple Table Relationship 【发布时间】:2021-11-18 03:45:08 【问题描述】:

这是一个很长的帖子,提前抱歉。

我有几个关于下图的问题。

    如何为这些表创建关系? (试过“belongsToMany”和“hasMany”) 我应该使用 Eloquent 还是 Query Builder 来获得想要的结果? (图片附在下面以获得所需的结果) “client_order_items”是数据透视表吗? 如何区分数据透视表?是不是因为表有多个 外键? 如何从“Manufacturer”模型访问“images”表? “hasOneThrough / hasManyThrough”可以实现这一点吗? 仅使用 Eloquent 或 DB Query 是否可以达到预期的结果?
//sample:
Manufacturers::find(2)->client_order_items->cars->images->car_image

我尝试将“client_order_items”视为数据透视表,然后在“Manufacturer”、“Car”和“Car”中使用“belongsToMany”建立关系“ClientOrder”模型。

// App\Model\Manufacturer.php
public function client_orders() 
    return $this->belongsToMany(ClientOrder::class, 
           "client_order_items", "manufacturer_id", "client_order_id")
           ->withPivot('id', 'quantity', 'car_id');;

public function cars() 
    return $this->belongsToMany(Car::class, 
           "client_order_items", "manufacturer_id", "car_id");


// App\Model\Car.php
public function client_orders() 
    return $this->belongsToMany(ClientOrder::class, 
           "client_order_items", "car_id", "client_order_id");

public function manufacturers() 
    return $this->belongsToMany(Manufacturer::class, 
           "client_order_items", "car_id", "manufacturer_id");


// App\Model\ClientOrder.php
public function cars() 
    return $this->belongsToMany(Manufacturer::class, 
           "client_order_items", "client_order_id", "car_id");

public function manufacturers() 
    return $this->belongsToMany(Manufacturer::class, 
           "client_order_items", "client_order_id", "manufacturer_id");

我也尝试过“hasMany”关系:

// App\Model\Manufacturer.php
public function client_order_items() 
    return $this->hasMany(ClientOrderItems::class);

// App\Model\Cars.php
public function client_order_items() 
    return $this->hasMany(ClientOrderItems::class);

// App\Model\ClientOrder.php
public function client_order_items() 
    return $this->hasMany(ClientOrderItems::class);

// App\Model\ClientOrderItems.php
public function car() 
    return $this->belongsTo(Car::class);

public function manufacturer() 
    return $this->belongsTo(Manufacturer::class);

public function client_order() 
    return $this->belongsTo(ClientOrder::class);

如果我做了这样的事情,我的目标是得到结果:

// Manufacturer::find(2)->client_orders

// Desired Result:
[
    
        "client_order_id": 88062,
        "first_name": "Clark",
        "last_name": "Kent",
        "order_items": [
            
                "client_order_item_id": 37394,
                "quantity": 1,
                "car_id": 68,
                "image": "path_img1"
            
        ]
    ,
    
        "client_order_id": 60978,
        "first_name": "Bruce",
        "last_name": "Wayne",
        "order_items": [
            
                "client_order_item_id": 79913,
                "quantity": 1,
                "car_id": 68,
                "image": "path_img1"
            ,
            
                "client_order_item_id": 84743,
                "quantity": 1,
                "car_id": 95,
                "image": "path_img2"
            
        ]
    
]

但我目前得到的结果(使用“belongsToMany”)是:

// Manufacturer::find(2)->client_orders

// Current Result:
[
    
        "id": 88062,
        "first_name": "Clark",
        "last_name": "Kent",
        "pivot": 
            "manufacturer_id": 2,
            "client_order_id": 88062,
            "id": 37394,
            "quantity": 1,
            "car_id": 68
        
    ,
    
        "id": 60978,
        "first_name": "Bruce",
        "last_name": "Wayne",
        "pivot": 
            "manufacturer_id": 2,
            "client_order_id": 60978,
            "id": 79913,
            "quantity": 1,
            "car_id": 68
        
    ,
    
        "id": 60978,
        "first_name": "Bruce",
        "last_name": "Wayne",
        "pivot": 
            "manufacturer_id": 2,
            "client_order_id": 60978,
            "id": 84743,
            "quantity": 1,
            "car_id": 95
        
    
]

再次为这篇长文感到抱歉。 提前谢谢你。

【问题讨论】:

【参考方案1】:

经过几个小时的实验和阅读,我得到了我想要的结果。

建立关系:

Manufacturer 模型与“ClientOrder”具有“belongsToMany”关系

// App\Model\Manufacturer
public function client_orders() 
    return $this->belongsToMany(ClientOrder::class, 'client_order_items', 'manufacturer_id', 'client_order_id');

“Car”和“Image”模型具有“hasMany”关系。这将使我们能够从“ClientOrderItems”模型访问“Image”模型。

// App\Models\Car
public function image() 
    return $this->belongsTo(Image::class);
 
 
// App\Models\Image
public function cars() 
    return $this->hasMany(Car::class);

为模型创建访问器

在“ClientOrder”模型中,为“order_items”键创建一个访问器。这将从“OrderLineItems”中获取与“manufacturer_id”和“client_order_id”相关的行。

// App\Models\ClientOrder
protected $appends = ["order_items"];

public function getOrderItemsAttribute() 
    $items = ClientOrderItems::where("manufacturer_id", '=', $this->pivot->manufacturer_id)
        ->where("client_order_id","=",$this->pivot->client_order_id)
        ->select(["id as client_order_item_id","car_id","quantity"])
        ->get();
    return $items;

在“ClientOrderItems”枢轴模型中,为“图像”创建一个访问器。

// App\Models\ClientOrderItems
protected $appends = ["image"];

public function getImageAttribute() 
    return Car::find($this->car_id)->image->car_image;

上面 2 个代码的结果如下所示:

[
    
        "client_order_item_id": 79913,
        "quantity": 1,
        "car_id": 68,
        "image": "path_img1"
     ,
     
        "client_order_item_id": 84743,
        "quantity": 1,
        "car_id": 95,
        "image": "path_img2"
     
]

有关访问器和突变器的更多信息: https://laravel.com/docs/8.x/eloquent-mutators#accessors-and-mutators

检索记录

要获取与manufacturer_id相关的“客户订单”,请使用:

/// App\Http\Controllers\ManufacturerController;
public function index() 
    $client_order = Manufacturer::find($manufacturer_id)->client_orders->unique("id")->values();

上面的代码只会从“client_orders”表中获取唯一的行。在访问器的帮助下为每一行附加相关的“order_items”。

[
    
        "client_order_id": 88062,
        "first_name": "Clark",
        "last_name": "Kent",
        "order_items": [
            
                "client_order_item_id": 37394,
                "quantity": 1,
                "car_id": 68,
                "image": "path_img1"
            
        ]
    ,
    
        "client_order_id": 60978,
        "first_name": "Bruce",
        "last_name": "Wayne",
        "order_items": [
            
                "client_order_item_id": 79913,
                "quantity": 1,
                "car_id": 68,
                "image": "path_img1"
            ,
            
                "client_order_item_id": 84743,
                "quantity": 1,
                "car_id": 95,
                "image": "path_img2"
            
        ]
    
]

【讨论】:

以上是关于Laravel 8 多表关系的主要内容,如果未能解决你的问题,请参考以下文章

Laravel - 具有关系的多表插入

laravel Eloquent ORM 多表插入

laravel 关联查询 表一、表二、两个表的关联表

Laravel 8 工厂的多重关系

Laravel 多表子查询

与属性 laravel 8 的关系