Laravel 如何在用户和产品之间创建正确的 ManyToMany 关系

How to create a correct ManyToMany relationship between a user and a product in Laravel

我正在与 Laravel 5.8 一起开发一个在线商店项目,在这个项目中,我想添加“添加到收藏夹”功能,以便用户将产品添加到他们最喜欢的列表中。

所以我创建了一个这样的模型:

class FavouriteProduct extends Model
{
    protected $table = 'favourite_products';
    protected $fillable = ['usr_id','prd_id'];

    public function users()
    {
       return $this->belongsToMany(User::class, 'favourite_products', 'id', 'usr_id');
    }

    public function products()
    {
       return $this->belongsToMany(Product::class, 'favourite_products', 'id', 'prd_id');
    }
}

在产品模型中,我添加了这个:

public function favourites()
    {
        return $this->belongsToMany(Product::class, 'favourite_products', 'prd_id', 'id');
    }

这是用户模型:

public function favourites()
    {
        return $this->belongsToMany(FavouriteProduct::class, 'favourite_products', 'usr_id', 'id');
    }

现在我想确保我已经正确设置了关系。

两个模型中不能有 2 个相同命名的方法!在用户模型中可以是 favourites(),但在产品模型中 favourites() 允许认为该产品可能有最喜欢的用户。您应该有一个描述性的名称,以便更容易理解您的代码。学到很多from this tutorial,推荐给大家

例如在您的用户模型中: 您正在设置与产品的关系:因此更改 class:

public function favourites()
    {
        return $this->belongsToMany(Product::class, 'favourite_products', 'usr_id', 'product_id');
    }

我不确定键的顺序。

首先,一个选项是删除您的 FavouriteProduct 模型,但保留 favourite_products table。 (这是我的建议)。

或者,您也可以更改 FavourteProduct 以扩展 Pivot 而不是 Model,并将 ->using(FavouriteProduct::class) 添加到 User 上的两个最喜欢的关系和 Product.

我已经详细介绍了以下两种方法。


选项一:简单关系

如果您接受我的第一个建议,则需要进行以下更改。

在您的 Product 模型上,您需要添加以下关系:

public function favouritees()
    {
        return $this->belongsToMany(User::class, 'favourite_products', 'prd_id', 'usr_id')
            ->withTimestamps();
    }

在您的 User 模型上,您需要添加以下关系:

public function favourites()
    {
        return $this->belongsToMany(Product::class, 'favourite_products', 'usr_id', 'prd_id')
            ->withTimestamps();
    }

现在,您只需执行以下操作即可添加收藏夹:

$user = User::find($userId);
$product = Product::find($productId);

$user->favourites()->save($product);

选项 2:更复杂的 Pivot 模型

如果您打算向两个模型之间的 Pivot 关系添加其他信息和关系,最好只使用数据透视选项。

Product 型号上像这样

public function favouritees()
        {
            return $this->belongsToMany(User::class, 'favourite_products', 'prd_id', 'usr_id')->using(FavouriteProduct::class);
        }

User 型号上像这样

public function favourites()
    {
        return $this->belongsToMany(Product::class, 'favourite_products', 'usr_id', 'prd_id')->using(FavouriteProduct::class);
    }

但我建议您开始使用更 Laravel 标准的方法;它有很多好处,包括在学习过程中仍然能够按照文档中的示例进行操作。

使用 usr_idprd_id 之类的列除了让您的生活更艰难之外,确实没有任何区别。如果你使用了 user_idproduct_id,你就不需要将它们传递给每个关系来告诉 Laravel 你决定在 Laravel 上使用你的约定。

Laravel 会自动假设关系,所以如果你添加一个 belongsToMany,它会查看它所实现的 class,在这种情况下,User::class,它会自动使用键user_id。它还会查看关系中的 class,例如Product::class 并使用 product_id。也就是说,当然,除非你告诉它像你所做的那样专门使用某些东西。

最后,你可以自由地这样做,有时你从别处继承数据库并被迫这样做。

执行此操作的简单方法是检查产品是否出现在用户收藏夹列表中

$data = Favourite::where(['user_id' => Auth::User()->id, 'product_ref_id' => $productId[1]])->get();

    if (sizeof($data) > 0) {
        Session()->put('snackmsg', 'Product already Exists in Wishlist');
    }else{      
        $Favourite = Favourite::create([
                                            'user_id' => Auth::User()->id,
                                            'product_ref_id' => $productId[1],
                                    ]);
        $totalFavourite = Favourite::where('user_id',Auth::User()->id)->count();
        Session()->forget('totalFavourite');
        Session()->put('totalFavourite', $totalFavourite);
        Session()->put('snackmsg', 'Added to Wishlist');
    }