【问题标题】:Laravel Eloquent 嵌套查询
【发布时间】:2015-06-27 08:50:38
【问题描述】:

我正在使用 Laravel 并陷入困境。我有以下型号:

  • 类别
  • 产品
  • 类别产品

CategoryProduct 持有关于哪个产品属于哪个类别的信息(一个产品可能属于多个类别)。

现在,当我想加载属于特定类别的所有产品时,我需要在 ProductCategoryProduct 上运行查询,这是我遇到的问题。

我尝试了以下方法,但没有成功:

$products = Product::where('status', '=', 'active')
->where('category_id', '=', $category_id)
->take($count)
->skip($skip)
->get();

显然,它会说category_id 不是一个列。

这是我的数据库和模型结构:

类别表

身份证, 姓名, 等等

产品表

身份证, 姓名, 货号, 等等

category_products 表

身份证, product_id,(Product.id 的外键) category_id,(Category.id 的外键) 等等

产品型号

class Product extends Eloquent {

protected $table = 'products';

protected $hidden = array();

    public static $rules = array('name' => 'required|min:3');

}

类别模型

class Category extends Eloquent {

protected $table = 'categories';

public static $rules = array('name' => 'required|min:3');

}

类别产品型号

<?php

class CategoryProduct extends Eloquent {

protected $table = 'category_products';

public function product()
{
    return $this->belongsTo('Product');
}

public function category()
{
    return $this->belongsTo('Category');
}
}

更新

关于此的新问题

我正在尝试展示产品。如果没有通过类别(值为-1),那么我将显示所有产品,否则我将显示来自通过的类别的产品。

现在,当我展示所有产品时,这些产品可能已经存在于一个类别中。我想为已经在一个类别中的产品显示勾选的复选框。我正在做这样的事情:

if($category_id==-1)
        $products = Product::where('status', '=', 'active')->take($count)->skip($skip)->get();
    else{
        $products = Product::whereHas('categories', function($q) use ($category_id)
        {
            $q->where('category_id', $category_id);
        })->where('status', 'active')
            ->take($count)
            ->skip($skip)
            ->get();
    }

category_products 表有 product_id、category_id 作为列。

现在,查询:

$products = Product::where('status', '=', 'active')->take($count)->skip($skip)->get();

将仅从 products 表中挑选产品。如果我在 category_products 中检查每个产品是否存在,那么对于大量产品的数据库查询将过多。

任何想法,如何实现这一点。我希望我能够清除我的情况。谢谢

【问题讨论】:

  • 查看has/whereHas函数。

标签: laravel eloquent relationship


【解决方案1】:

CategoryProduct 模型应该不是必需的,除非除了 product_id 和 category_id 之外还有其他字段指向其他关系。

CategoryProduct 模型上建立关系的方法是必要的。

Category中,添加关系函数...

public function products()
{
    return $this->belongsToMany('Product', 'category_products');
}

在您的 Product 模型中,对类别执行相同操作。

public function categories()
{
    return $this->belongsToMany('Category', 'category_products');
}

然后您可以使用您的关系方法和whereHas()查询属于该类别的有效产品

$products = Product::whereHas('categories', function($q) use ($category_id)
{
    $q->where('id', $category_id);
})->where('status', 'active')
->take($count)
->skip($skip)
->get();

【讨论】:

  • 嗨 user3158900 感谢您的快速回复。使用 CategoryProduct 是因为一个产品可能属于多个类别。
  • @Ashutosh 多对多数据透视表不需要模型。查看我的答案中的文档链接
  • 好的,明白你想说的了,再次感谢。现在查看文档。
  • 当你在父表上使用belongsToMany 时,Laravel 将为你处理和管理数据透视表(category_prodcuts)。您唯一需要做的就是告诉 Laravel 该表的名称是什么,我已在答案中编辑/添加了该名称。
  • @user1669496 嗨,但是如果产品归供应商所有怎么办?而不是$product = Products::whereHas(),而是$vendor = Vendors::whereHas()。供应商是产品的父级。这怎么可能在多个嵌套关系下使用条件?
【解决方案2】:

在多对多关系中,您不需要数据透视表模型。查看 Eloquent 文档的 this section 以获得进一步的解释。

您仍然需要创建迁移来设置数据透视表(或者如果您不使用迁移,则手动执行),而不是模型。相反,为Category 创建一个函数来指定关系:

public function products()
{
    return $this->belongsToMany('App\Product', 'category_products');
    // - You might need to adjust the namespace of App\Product
    // - category_products refers to the pivot table name
}

同样,Product 需要一个类似的公共函数。

然后你可以反过来做,找到类别,然后列出所有相关产品:

$products = Category::find($category_id)
   ->products()
   ->where('status', 'active')
   ->take($count)
   ->skip($skip)
   ->get();

This question 也可能与您的相关。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-15
    • 1970-01-01
    • 1970-01-01
    • 2019-02-26
    • 1970-01-01
    • 2021-08-23
    • 2021-05-27
    相关资源
    最近更新 更多