我有以下表格:
订单
line_items
制品
甲采购订单中包含多个行项目,并且每个订单项具有一个产品和数量的字段(" 数量 ").
以下是我定义Laravel模型的方法:
产品型号:
class Product extends Model
{
public function lineitems()
{
return $this->hasMany('App\LineItem');
}
}
Run Code Online (Sandbox Code Playgroud)
LineItem模型:
class LineItem extends Model
{
public function purchase_order()
{
return $this->belongsTo('App\PurchaseOrder', 'purchase_order_id');
}
public function product()
{
return $this->hasOne('App\Product', 'product_id');
}
}
Run Code Online (Sandbox Code Playgroud)
PurchaseOrder型号:
class PurchaseOrder extends Model
{
public function lineitems()
{
return $this->hasMany('App\LineItem');
}
}
Run Code Online (Sandbox Code Playgroud)
我希望得到所有'line_items.qty'的SUM,其中'product.id'由'purchase_order.status'过滤.
如何在Model函数中编写查询,以便我可以使用它通过Blade @foreach遍历所有产品?
先感谢您!
如果您想获得更快的速度并一次获得所有内容,那么您可以尝试以下查询:
$products = Product::selectRaw('products.*, sum(line_items.qty) as qty_sum')
->join('line_items', 'line_items.product_id', '=', 'products.id')
->join('purchase_orders', 'purchase_orders.id', '=', 'line_items.purchase_order_id')
->where('purchase_orders.status', 'sold')
->groupBy('products.id')
->get();
Run Code Online (Sandbox Code Playgroud)
但是如果 MySql 必须接受整个分组,其中一列始终与其他列匹配,那么您的数据库。
但如果您只想坚持 Laravel 关系,请执行以下步骤。
1-当您的表名是复数、PK 是id
、FK 是表名单数且带有_id
ex (table products(id), table line_items(product_id)) 时,不需要在关系中指定外键。
2-由于这是多对多的情况,您不一定需要为中间表定义模型line_items
,您可以将其用于特殊和快速查询,但您可以通过 Laravel Pivot 系统处理其上的 CRUD。您可以了解有关 Pivot 的更多信息https://laravel.com/docs/5.7/eloquent-relationships#many-to-many
检索中间表列
正如您已经了解到的,处理多对多关系需要存在中间表。Eloquent 提供了一些与此表交互的非常有用的方法。例如,假设我们的 User 对象有许多与之相关的 Role 对象。访问此关系后,我们可以使用模型上的数据透视属性来访问中间表:
所以你的模型可能看起来像这样:
产品型号:
class Product extends Model
{
public function purchaseOrders()
{
return $this->belongsToMany('App\PurchaseOrder', 'line_items')->withPivot('qty')->withTimestamps();
}
public function soldPurchaseOrders()
{
return $this->belongsToMany('App\PurchaseOrder', 'line_items')
->where('status', 'sold')
->withPivot('qty')->withTimestamps();
}
}
Run Code Online (Sandbox Code Playgroud)
采购订单型号:
class PurchaseOrder extends Model
{
public function products()
{
return $this->belongsToMany('App\Product', 'line_items')->withPivot('qty')->withTimestamps();
}
}
Run Code Online (Sandbox Code Playgroud)
如果您的数据透视表有,列,请使用->withPivot('field1', 'field2', 'etc')
, 。并在查询生成器中使用前缀 +attribute 以及结果对象方法中的 +attribute 访问枢轴值,例如 : 。->withTimestamps()
created_at
updated_at
pivot_
pivot->
$products->first()->pivot->qty
如果您仍想使用 LineItem 模型,请将 Product 关系更改为belongsTo
。
订单项型号:
class LineItem extends Model
{
public function purchaseOrder()
{
return $this->belongsTo('App\PurchaseOrder');
}
public function product()
{
return $this->belongsTo('App\Product');
}
}
Run Code Online (Sandbox Code Playgroud)
3-最后要检索具有数量 SUM 的产品,请使用以下代码:
使用预先加载在 1 个请求中一次性自动加载所有产品的采购订单,以避免对数据库发出 N 个产品 + 1 个请求。https://laravel.com/docs/5.7/eloquent-relationships#eager-loading
$products = Product::with('soldPurchaseOrders')->get();
foreach($products as $product) {
$qtySum = $product->soldPurchaseOrders->sum('pivot.qty');
echo '<br/> Product '.$product->id.' - '.$product->name.' - '.$qtySum;
}
Run Code Online (Sandbox Code Playgroud)
所以最后,Laravel 将使用 INNER JOIN 查询来转换它,就像上面的第一个示例一样,但仅使用精美的设计和数据透视表。
编辑 - - -
在 OP 将订单状态指定为 后sold
,我已更新代码以使用已售出。
编辑2-----
替换$product->pivot->qty
为$qtySum
. 致电关系后即可获得枢轴数量,soldPurchaseOrders
例如:
foreach($product->soldPurchaseOrders as $order) {
echo '<br/>Order .'$order->id.' - '.$order->pivot->qty;
}
Run Code Online (Sandbox Code Playgroud)