SQL查询转符合最佳实践的Laravel Eloquent/Model写法咨询
Laravel折扣查询优化方案
优化思路
- 避免直接使用
whereRaw拼接SQL,杜绝SQL注入风险 - 复用折扣计算逻辑,提升代码可维护性
- 利用Laravel查询构造器原生方法提升代码可读性
基础实现(控制器内直接编写)
首先需要引入DB门面:
use Illuminate\Support\Facades\DB;
优化后的控制器代码:
$discount_range = Config::get('constants.discount_range')[$type]; $products = Product::selectRaw('*, (((product_price - product_sell_price) / product_sell_price)*100) as p_discount') ->whereNotNull('product_price') // 对应原SQL的大于25的条件可取消下方注释使用 // ->where(DB::raw('(((product_price - product_sell_price) / product_sell_price)*100)'), '>', 25) // 对应现有需求的区间判断 ->whereBetween(DB::raw('(((product_price - product_sell_price) / product_sell_price)*100)'), $discount_range) ->orderBy('product_sell_price', $sort_by) ->paginate($perpage);
进阶最佳实践(本地作用域封装)
你可以将折扣判断逻辑封装到Product模型的本地作用域中,进一步简化控制器代码,提升逻辑复用性:
模型代码(app/Models/Product.php)
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Facades\DB; class Product extends Model { // 其他原有模型代码... /** * 筛选符合指定折扣区间的商品 */ public function scopeWhereDiscountBetween($query, array $discountRange) { return $query->whereBetween( DB::raw('(((product_price - product_sell_price) / product_sell_price)*100)'), $discountRange ); } /** * 筛选折扣大于指定值的商品 */ public function scopeWhereDiscountGreaterThan($query, int $discount) { return $query->where( DB::raw('(((product_price - product_sell_price) / product_sell_price)*100)'), '>', $discount ); } }
简化后的控制器代码
$discount_range = Config::get('constants.discount_range')[$type]; $products = Product::selectRaw('*, (((product_price - product_sell_price) / product_sell_price)*100) as p_discount') ->whereNotNull('product_price') ->whereDiscountBetween($discount_range) ->orderBy('product_sell_price', $sort_by) ->paginate($perpage);
实现说明
- 这里仅用
DB::raw包裹固定的字段运算逻辑,没有外部输入变量,不存在SQL注入风险,完全符合Laravel安全规范 - 所有动态参数都会由Laravel查询构造器自动做参数绑定,解决了原代码中直接拼接
$discount_range变量的注入隐患 - 计算逻辑仅需定义一次,后续修改折扣计算规则时无需多处修改,维护成本更低
内容的提问来源于stack exchange,提问作者Ram Chander
相关产品推荐
相关产品推荐

