You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel原生SQL语句中替换PHP变量的方法

在Laravel原生SQL中安全替换PHP变量的方法

直接拼接PHP变量到原生SQL里会引发SQL注入风险,Laravel提供了安全的参数绑定方式,推荐用以下两种方法:

方法一:位置占位符绑定

在SQL语句中用?代替需要替换的变量,然后将变量作为第二个参数传入DB::select(),参数顺序要和占位符一一对应:

// 定义PHP变量
$shift1Id = '48c73e3d-57de-4fea-aae4-7222d7e6afed';
$shift2Id = '463ec995-cfad-46ff-8e65-3115e6e651c5';
$shift3Id = '0a792c5f-84a6-4534-818c-427cfe8cd3ca';
$productId = '3516c43b-ffe3-4e90-9d93-924a9865c9cd';
$customerId = 'd9916741-ca61-4a57-b281-15c80fad833c';
$startDate = '2023-04-07';
$endDate = '2023-04-09';

// 替换SQL中的硬编码值为?占位符
$query = <<<SQL
SELECT day, date, product1_shift1, product1_shift2, product1_shift3, 
COALESCE(product1_shift1, 0) + COALESCE(product1_shift2, 0) + COALESCE(product1_shift3, 0) AS total_product1_qty
FROM (
    SELECT DAYNAME(date) AS day, DATE_FORMAT(date, "%d-%m-%Y") AS date,
        (SELECT SUM(qty) AS product1_shift1
        FROM bill_details 
        JOIN bills ON bills.bill_id=bill_details.bill_id
        WHERE bills.shift_id=?
        AND bills.date=bills_master.date
        AND bills_master.customer_id=bills.customer_id
        AND bill_details.product_id=?) AS product1_shift1,
        (SELECT SUM(qty) AS product1_shift2
        FROM bill_details 
        JOIN bills ON bills.bill_id=bill_details.bill_id
        WHERE bills.shift_id=?
        AND bills.date=bills_master.date
        AND bills_master.customer_id=bills.customer_id
        AND bill_details.product_id=?) AS product1_shift2,
        (SELECT SUM(qty) AS product1_shift3
        FROM bill_details 
        JOIN bills ON bills.bill_id=bill_details.bill_id
        WHERE bills.shift_id=?
        AND bills.date=bills_master.date
        AND bills_master.customer_id=bills.customer_id
        AND bill_details.product_id=?) AS product1_shift3
    FROM bills bills_master
    WHERE bills_master.date BETWEEN ? AND ?
        AND bills_master.customer_id=?
    GROUP BY bills_master.date
) subquery_alias
SQL;

// 传入参数数组,顺序和占位符一致
dd(DB::select($query, [
    $shift1Id, $productId,
    $shift2Id, $productId,
    $shift3Id, $productId,
    $startDate, $endDate,
    $customerId
]));

方法二:命名占位符绑定

用:变量名的形式定义占位符,参数数组用键值对传递,可读性更强,不用担心参数顺序错误:

// 定义PHP变量
$shift1Id = '48c73e3d-57de-4fea-aae4-7222d7e6afed';
$shift2Id = '463ec995-cfad-46ff-8e65-3115e6e651c5';
$shift3Id = '0a792c5f-84a6-4534-818c-427cfe8cd3ca';
$productId = '3516c43b-ffe3-4e90-9d93-924a9865c9cd';
$customerId = 'd9916741-ca61-4a57-b281-15c80fad833c';
$startDate = '2023-04-07';
$endDate = '2023-04-09';

// 替换SQL中的硬编码值为命名占位符
$query = <<<SQL
SELECT day, date, product1_shift1, product1_shift2, product1_shift3, 
COALESCE(product1_shift1, 0) + COALESCE(product1_shift2, 0) + COALESCE(product1_shift3, 0) AS total_product1_qty
FROM (
    SELECT DAYNAME(date) AS day, DATE_FORMAT(date, "%d-%m-%Y") AS date,
        (SELECT SUM(qty) AS product1_shift1
        FROM bill_details 
        JOIN bills ON bills.bill_id=bill_details.bill_id
        WHERE bills.shift_id=:shift1_id
        AND bills.date=bills_master.date
        AND bills_master.customer_id=bills.customer_id
        AND bill_details.product_id=:product_id) AS product1_shift1,
        (SELECT SUM(qty) AS product1_shift2
        FROM bill_details 
        JOIN bills ON bills.bill_id=bill_details.bill_id
        WHERE bills.shift_id=:shift2_id
        AND bills.date=bills_master.date
        AND bills_master.customer_id=bills.customer_id
        AND bill_details.product_id=:product_id) AS product1_shift2,
        (SELECT SUM(qty) AS product1_shift3
        FROM bill_details 
        JOIN bills ON bills.bill_id=bill_details.bill_id
        WHERE bills.shift_id=:shift3_id
        AND bills.date=bills_master.date
        AND bills_master.customer_id=bills.customer_id
        AND bill_details.product_id=:product_id) AS product1_shift3
    FROM bills bills_master
    WHERE bills_master.date BETWEEN :start_date AND :end_date
        AND bills_master.customer_id=:customer_id
    GROUP BY bills_master.date
) subquery_alias
SQL;

// 传入键值对参数
dd(DB::select($query, [
    'shift1_id' => $shift1Id,
    'shift2_id' => $shift2Id,
    'shift3_id' => $shift3Id,
    'product_id' => $productId,
    'start_date' => $startDate,
    'end_date' => $endDate,
    'customer_id' => $customerId
]));

注意事项

  • 绝对不要用字符串拼接(比如"WHERE shift_id='$shiftId'")或双引号插值的方式替换变量,这会直接暴露SQL注入漏洞。
  • 两种绑定方式都会自动处理变量的转义,确保SQL语句的安全性。

内容的提问来源于stack exchange,提问作者DenjanD

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 03:25:00