![](/img/trans.png)
[英]Laravel eloquent orderby related model's column sum (has Many Relationship)
[英]Get SUM of a related column filtered by a field in the parent model in Laravel Eloquent
我有以下表格:
訂單
line_items
制品
采購訂單包含多個訂單項 ,每個訂單項都有一個產品和一個數量字段(' qty ')。
以下是我定義Laravel模型的方法:
產品型號:
class Product extends Model
{
public function lineitems()
{
return $this->hasMany('App\LineItem');
}
}
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');
}
}
PurchaseOrder型號:
class PurchaseOrder extends Model
{
public function lineitems()
{
return $this->hasMany('App\LineItem');
}
}
我希望得到所有'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();
但是你的數據庫,如果MySql必須接受整個分組,其中一列總是與其他列匹配。
但是,如果您只想堅持Laravel關系,請執行以下步驟。
1-當你的表名是復數時,PK是id
,而FK是表名單數,帶有_id
ex(table products(id),table line_items(product_id)),不需要在Relations中指定外鍵。
2-由於它是多對多的情況,您不一定要為中間表line_items
定義模型,您可以將它用於特殊和快速查詢,但您可以通過Laravel Pivot系統處理它上面的CRUD。 您可以了解有關Pivot的更多信息https://laravel.com/docs/5.7/eloquent-relationships#many-to-many
檢索中間表列
正如您已經了解的那樣,處理多對多關系需要存在中間表。 Eloquent提供了一些與此表交互的非常有用的方法。 例如,假設我們的User對象有許多與之相關的Role對象。 訪問此關系后,我們可以使用模型上的pivot屬性訪問中間表:
所以你的模型看起來像這樣:
產品型號:
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();
}
}
PurchaseOrder型號:
class PurchaseOrder extends Model
{
public function products()
{
return $this->belongsToMany('App\Product', 'line_items')->withPivot('qty')->withTimestamps();
}
}
如果您的數據透視表有created_at
, updated_at
列,請使用->withPivot('field1', 'field2', 'etc')
和->withTimestamps()
。 並在查詢構建器中使用前綴pivot_
+屬性訪問數據透視值,並在結果對象方法中使用pivot->
+屬性,例如: $products->first()->pivot->qty
。
如果您仍想使用LineItem模型, belongsTo
Product relation更改為belongsTo
。
LineItem模型:
class LineItem extends Model
{
public function purchaseOrder()
{
return $this->belongsTo('App\PurchaseOrder');
}
public function product()
{
return $this->belongsTo('App\Product');
}
}
3-最后用qty的SUM檢索產品使用以下代碼:
在1個請求中使用預先加載來自動加載所有產品的采購訂單,以避免N-Products + 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;
}
所以最后,Laravel將使用INNER JOIN查詢轉換它,如上面的第一個例子,但只有花哨的設計和數據透視表。
編輯 - - -
OP指定訂單狀態為sold
,我已更新要使用已銷售的代碼。
編輯2 -----
用$qtySum
替換$product->pivot->qty
$qtySum
$product->pivot->qty
。 在調用soldPurchaseOrders
關系之后,將提供樞軸數量,例如:
foreach($product->soldPurchaseOrders as $order) {
echo '<br/>Order .'$order->id.' - '.$order->pivot->qty;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.