Laravel 4.2 n+1 没有预先加载
Laravel 4.2 n+1 without eager loading
我有一个 table 的产品
products
------------------------------------------------
id product_code purchase_type quantity
1 106 new 1
2 107 renew 3
和产品价目表
price_list
----------------------------------------------------------------------
id product_code purchase_type minimum maximum unit_price
1 106 new 1 25 20
2 106 new 26 50 16
3 106 new 51 100 14
当我在页面上显示产品时,我需要用公式显示价格
getPrice(product_code, purchase_type, quantity) for every product
正在使用
foreach(Product::all() as $product){
{{ $product->product_code }}
{{ $product->purchase_type }}
{{ $product->quantity }}
{{ PriceList::getPrice($product->product_code, $product->purchase_type, $product->quantity) }} - this one is the n+1 problem
}
PriceList::getPrice() 类似于:
public static function getPrice($productCode, $purchaseType, $quantity){
return PriceList::where('product_code', $productCode)
->where('purchase_type', $purchaseType)
->where('minimum', '>=', $quantity)
->where('maximum', '<=', $quantity)
->get()->first()->unit_price;
}
我似乎找不到更有效的方法。
当我展示超过 1000 种产品时,它会变得非常慢。
我似乎找不到使用预加载的方法。
从内部循环调用模型来获取数据不是一个好主意。
与其这样做,不如按照下面的方式进行。
您应该在 Product 和 PriceList 表之间定义 relationship。
模型中Product.php
public function price_list(){
return $this->hasMany('PriceList','product_code');
}
模型中PriceList.php
public function product(){
return $this->belongsTo('Product','product_code');
}
在控制器文件中
$products = Product::with('price_list')->get();
return View::make('your_view')->with('products', $products);
在查看文件中(文件必须有扩展名 .blade.php 才能使用下面的语法)
@foreach($products as $product)
{{ $product }}
@endforeach
注意:- 在控制器中打印 $products 以检查结果。
我找到了 mysql、
的方法
SELECT
`products`.`id` AS `product_id`,
`products`.`product_code` AS `product_product_code`,
`products`.`purchase_type` AS `product_purchase_type`,
`products`.`quantity` AS `product_quantity`,
`price_list`.`product_code` AS `price_list_product_code`,
`price_list`.`purchase_type` AS `price_list_purchase_type`,
`price_list`.`minimum` AS `price_list_minimum`,
`price_list`.`maximum` AS `price_list_maximum`,
`price_list`.`unit_price` AS `price_list_unit_price`
FROM
`products`
LEFT JOIN `price_list` ON `products`.`product_code` = `price_list`.`product_code`
AND `products`.`purchase_type` = price_list.purchase_type
AND `products`.`quantity` >= price_list.minimum
AND `products`.`quantity` <= price_list.maximum
ORDER BY
`products`.`id` ASC
我有一个 table 的产品
products
------------------------------------------------
id product_code purchase_type quantity
1 106 new 1
2 107 renew 3
和产品价目表
price_list
----------------------------------------------------------------------
id product_code purchase_type minimum maximum unit_price
1 106 new 1 25 20
2 106 new 26 50 16
3 106 new 51 100 14
当我在页面上显示产品时,我需要用公式显示价格
getPrice(product_code, purchase_type, quantity) for every product
正在使用
foreach(Product::all() as $product){
{{ $product->product_code }}
{{ $product->purchase_type }}
{{ $product->quantity }}
{{ PriceList::getPrice($product->product_code, $product->purchase_type, $product->quantity) }} - this one is the n+1 problem
}
PriceList::getPrice() 类似于:
public static function getPrice($productCode, $purchaseType, $quantity){
return PriceList::where('product_code', $productCode)
->where('purchase_type', $purchaseType)
->where('minimum', '>=', $quantity)
->where('maximum', '<=', $quantity)
->get()->first()->unit_price;
}
我似乎找不到更有效的方法。 当我展示超过 1000 种产品时,它会变得非常慢。 我似乎找不到使用预加载的方法。
从内部循环调用模型来获取数据不是一个好主意。
与其这样做,不如按照下面的方式进行。
您应该在 Product 和 PriceList 表之间定义 relationship。
模型中Product.php
public function price_list(){
return $this->hasMany('PriceList','product_code');
}
模型中PriceList.php
public function product(){
return $this->belongsTo('Product','product_code');
}
在控制器文件中
$products = Product::with('price_list')->get();
return View::make('your_view')->with('products', $products);
在查看文件中(文件必须有扩展名 .blade.php 才能使用下面的语法)
@foreach($products as $product)
{{ $product }}
@endforeach
注意:- 在控制器中打印 $products 以检查结果。
我找到了 mysql、
的方法SELECT
`products`.`id` AS `product_id`,
`products`.`product_code` AS `product_product_code`,
`products`.`purchase_type` AS `product_purchase_type`,
`products`.`quantity` AS `product_quantity`,
`price_list`.`product_code` AS `price_list_product_code`,
`price_list`.`purchase_type` AS `price_list_purchase_type`,
`price_list`.`minimum` AS `price_list_minimum`,
`price_list`.`maximum` AS `price_list_maximum`,
`price_list`.`unit_price` AS `price_list_unit_price`
FROM
`products`
LEFT JOIN `price_list` ON `products`.`product_code` = `price_list`.`product_code`
AND `products`.`purchase_type` = price_list.purchase_type
AND `products`.`quantity` >= price_list.minimum
AND `products`.`quantity` <= price_list.maximum
ORDER BY
`products`.`id` ASC