Php 我应该使用什么样的连接,或者我应该为此制作模型?

Php 我应该使用什么样的连接,或者我应该为此制作模型?,php,sql,laravel,join,eloquent,Php,Sql,Laravel,Join,Eloquent,我有三张表-购物车,购物车产品和产品 它们的结构如下所示: 手推车: id, employee_id, name, paid 购物车产品: id, cart_id, product_id, amount 产品: id, name, price 现在,在我的代码中,我抓取了所有未付的购物车: $carts = Cart::where('paid', false)->select('id')->get(); 并对其进行迭代: foreach ($carts as $key) {

我有三张表-
购物车
购物车产品
产品

它们的结构如下所示:

手推车:

id, employee_id, name, paid
购物车产品:

id, cart_id, product_id, amount
产品:

id, name, price
现在,在我的代码中,我抓取了所有未付的购物车:

$carts = Cart::where('paid', false)->select('id')->get();
并对其进行迭代:

foreach ($carts as $key) {
    $cart_products = DB::table('cart_products')
    ->where('cart_id', $key->id)
    ->get();

    $returnedCarts[] = [
        'id' => $key->id,
        'name' => $key->name,
        'products'=> $cart_products      
    ];
}

return response()->json($returnedCarts);
现在我的问题是,如何更改包含JSON的产品:

{
    "id": 1,
    "name": null,
    "products": [ //this is the cart_products table
        {
            "id": 1,
            "cart_id": 1,
            "product_id": 1,
            "amount": 2,
            "created_at": null,
            "updated_at": null
        }
    ]
},
为此:

{
    "id": 1,
    "name": null,
    "products": [ //this is data from the products table
        {
            "product_id": 1,
            "amount": 2, //but this is from the cart_products table
            "name": "This product name",
            "price" "$9,49"
        }
    ]
},
在foreach循环中没有其他查询。我应该使用哪种连接?我应该更改代码还是应该使用模型而不是DB facade


任何帮助都将不胜感激。

您可以利用Laravel的雄辩,和

首先,在模型中定义关系:

# Cart.php

use App\Product;

// ...

public function products()
{
    return $this->belongsToMany(Product::class)->withPivot('amount');
} //             ^^^^^^^^^^^^^^^relationship    ^^^^^^^^^aditional intermediate columns
然后,在控制器中,您可以执行以下操作:

# CartsController.php

use App\cart;

// ...

public function yourFunction()
{
    $carts = Cart
         ::with('products') // <-- Eager loading the relationship 'products'
         ->where('paid', false) // <-- constraining the query
         ->get();  // <-- executing the query.

    return $carts;
}
#CartsController.php
使用App\cart;
// ...
公共职能
{
$carts=购物车

::使用('products')//where('paid',false)//get();//您应该使用模型,因为您可以急切地加载产品并保存一些查询(稍后阅读更多内容),并且通过使用模型,您可以利用有说服力的API资源更好地控制输出(哪些字段、顺序、从何处获取它们等)

N+1查询问题 您现在遇到了N+1查询问题,因为您得到了所有N个未付购物车(1个查询),并且每个购物车都有自己的产品(N个查询,每个购物车一个)

实现模型关系 在购物车模型中,您可以设置与产品的关系,如下所示:

公共功能产品()
{
返回$this->belongtomany('App\Product')->withPivot('amount');
}
您还可以添加一个查询范围,以简单地保留where条件,该条件告诉您购物车在模型中而不是在控制器中是未付款的(稍后您将了解如何使用它):

公共函数($query)
{
返回$query->where('paid',false);
}
API资源 要实现雄辩的API资源,您必须:

  • 使用artisan为购物车和产品创建API资源类:
  • 这些命令将创建两个文件
    app/Http/Resources/Cart.php
    app/Http/Resources/Product.php

  • 编辑购物车资源以显示输出中所需的字段,否则将返回所有购物车字段:
  • //不要忘记顶部的use语句
    使用App\Http\Resources\Product作为ProductResource;
    //然后替换toArray方法
    公共功能待命($request)
    {
    //$this指的是当前购物车实例
    返回[
    'id'=>this->id,
    “名称”=>$this->name,
    //这行告诉我们如何使用产品API资源呈现此购物车的每个产品,
    //通过这种方式,您还可以控制每个产品模型的显示方式
    //在json响应中
    'products'=>ProductResource::collection($this->products)
    ];
    }
    
  • 编辑产品资源以按所需方式显示输出:
  • 公共功能待命($request)
    {
    //$this指的是当前产品实例
    //根据您的要求,您可以在这里设置字段及其值。
    返回[
    'product_id'=>$this->id,
    //此字段取自已加载的cart_product表
    //正如您指定的那样,使用->withPivot('amount')加载amount属性
    //产品()关系中的说明
    “金额”=>this->pivot->amount,
    “名称”=>$this->name,
    “价格”=>$this->price
    ];
    }
    
    在controller中,您现在可以为未付款的购物车加载所有产品,并使用API资源编辑将作为响应发送的内容,以仅显示所需的属性

    // Do not forget to import the Cart model and the Cart Resource at the top
    use App\Cart;
    use App\Http\Resources\Cart as CartResource;
    
    public function your_method()
    {
        // You can use the unpaid() query scope you added earlier
        // as a simple shorthand to ->where('paid', false') function
        // on the query builder.
        // ->with('products') will eager-load the products relationship
        // and therefore retrive the products associated to the carts you
        // are gonna retrive with just one additional query, not one for each cart.
        $carts = Cart::unpaid()->with('products')->get();
    
        return CartResource::collection($carts);
    }
    

    您可以查看有关API资源和快速加载的文档

    我喜欢您的答案,感谢您的详细解释。感谢您提供的所有详细信息,我学到了一些新的东西。+1为您提供,不过我将简化后的帖子标记为答案,但我认为这应该保持下去。
    php artisan make:resource Cart
    
    php artisan make:resource Product
    
    // Do not forget to import the Cart model and the Cart Resource at the top
    use App\Cart;
    use App\Http\Resources\Cart as CartResource;
    
    public function your_method()
    {
        // You can use the unpaid() query scope you added earlier
        // as a simple shorthand to ->where('paid', false') function
        // on the query builder.
        // ->with('products') will eager-load the products relationship
        // and therefore retrive the products associated to the carts you
        // are gonna retrive with just one additional query, not one for each cart.
        $carts = Cart::unpaid()->with('products')->get();
    
        return CartResource::collection($carts);
    }