如何仅在中间表中建立与外键的HasManyThrough关系?

问题描述 投票:0回答:2

我正在使用 Laravel v9.19 和 PHP 8.0 开发一个项目。

这是该项目数据库中与问题相关的部分:

Database

  • 一个用户可以有多个订单,但每个订单只能有一个用户(一对多关系)。
  • 一个订单只能有一件商品,但一件商品可以出现在多个订单中(多对一关系)。

这是一个 User 类:

class User extends Authenticatable
{
    // ...

    /**
     * Get orders of this user.
     * 
     * @return Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function orders(): HasMany
    {
        return $this->hasMany(Order::class, 'client_id');
    }
}

这是一个 Order 类:

class Order extends Model
{
    // ...

    /**
     * Get the client of this order.
     * 
     * @return Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function client(): BelongsTo
    {
        return $this->belongsTo(User::class, 'client_id');
    }

    /**
     * Get the ordered item.
     * 
     * @return Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function item(): BelongsTo
    {
        return $this->belongsTo(Item::class, 'item_id');
    }
}

这是一个 Item 类:

class Downloadable extends Model
{
    // ...

    /**
     * Get the orders having this item.
     * 
     * @return Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function orders(): HasMany
    {
        return $this->hasMany(Order::class, 'item_id');
    }
}

我想利用雄辩的关系以便能够:

  • 检索特定用户订购的所有商品。
  • 检索订购特定商品的所有用户。

我需要向 User 模型添加一个新方法:

    /**
     * Get items ordered by this user.
     * 
     * @return ???
     */
    public function items()
    {
        // What to do here?
    }

我需要向 Item 模型添加一个新方法:

    /**
     * Get users that ordered this item.
     * 
     * @return ???
     */
    public function users()
    {
        // What to do here?
    }

由于默认的 HasManyThrough 关系需要不同的表结构,并且我无法修改现有的表结构,因此这里不适用。

作为可能的解决方案之一,我正在考虑使用 staudenmeir/eloquent-has-many-deep,创建一个名为

order_item
的新中间表来将订单映射到项目,并使用以下代码,例如项目方法:

    /**
     * Get items ordered by this user.
     * 
     * @return ???
     */
    public function items()
    {
        return $this->hasManyDeep(
                    Item::class,
                    [Order::class, 'order_item']
            );
    }

如果存在无需外部库的 Laravel 解决方案,或者您知道更有效的方法,请分享给我。我很想知道这种情况下的最佳实践。

php laravel eloquent eloquent-relationship
2个回答
0
投票
class User extends Authenticatable
{
    // ...

    /**
     * Get all items ordered by the user.
     * 
     * @return Illuminate\Database\Eloquent\Relations\HasManyThrough
     */
    public function items(): HasManyThrough
    {
        return $this->hasManyThrough(Item::class, Order::class, 'client_id', 'id', 'id', 'item_id');
    }
}
class Item extends Model
{
    // ...

    /**
     * Get all users who ordered this item.
     * 
     * @return Illuminate\Database\Eloquent\Relations\HasManyThrough
     */
    public function users(): HasManyThrough
    {
        return $this->hasManyThrough(User::class, Order::class, 'item_id', 'id', 'id', 'client_id');
    }
}

0
投票

要定义 Laravel 中的 users、orders 和 items 表之间的关系,您需要使用 Eloquent ORM 的关系功能。根据典型的业务逻辑,您可以如何定义这些表之间的关系:

1。用户和订单:

一个用户可以有多个订单(一对多关系)。 订单属于单个用户。

在 Laravel 中,您将其定义为:

用户模型:

<?php 
    class User extends Model
    {
        public function orders()
        {
            return $this->hasMany(Order::class);
        }
    }

订购型号:

<?php

    class Order extends Model
    {
        public function user()
        {
            return $this->belongsTo(User::class);
        }
    }

2。订单和商品:

一个订单可以有很多商品(多对多关系)。 一个项目可以属于多个订单。

为此,您需要一个数据透视表(通常称为 order_item)来保存订单和商品之间的关系。

数据透视表迁移:

<?php

Schema::create('order_item', function (Blueprint $table) {
    $table->id();
    $table->foreignId('order_id')->constrained()->onDelete('cascade');
    $table->foreignId('item_id')->constrained()->onDelete('cascade');
    $table->timestamps();
});

在 Laravel 中,您将其定义为:

订购型号:

<?php

class Order extends Model
{
    public function items()
    {
        return $this->belongsToMany(Item::class);
    }
}

商品型号:

<?php

    class Item extends Model
    {
        public function orders()
        {
            return $this->belongsToMany(Order::class);
        }
    }

关系总结:

User -> hasMany -> Order.
Order -> belongsTo -> User.
Order -> belongsToMany -> Item.
Item -> belongsToMany -> Order.

此结构将允许用户下多个订单,每个订单可以有多个商品,每个商品都是多个订单的一部分。

© www.soinside.com 2019 - 2024. All rights reserved.