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);
}