在原始 sql 查询 Laravel 中插入变量
Posted
技术标签:
【中文标题】在原始 sql 查询 Laravel 中插入变量【英文标题】:Inserting a variable in a raw sql query Laravel 【发布时间】:2016-10-03 18:41:44 【问题描述】:我在控制器的一个函数中。
所以从表单中,我得到一个变量的值,比如:
$x = "whatever";
然后我需要在 WHERE 语句中嵌入该变量(因此,它的值)。如果我对值进行硬编码,它会带来正确的结果,但我已经尝试了各种方式来插入该变量但没有成功。好吧,假设我设法使用该变量,那么我将不得不研究绑定以避免 sql 注入,但到目前为止,我会说,看看该变量是否可以在查询中使用。
我试过了,双引号,串联。 $vx 。 , 花括号 $x, 像这样的 $variable 变量,但在某些情况下会给出语法错误,(连接),或者如果我只是在 author = $x 的地方嵌入这样的变量,它告诉我它可以'找不到名为 $x 的列
$x = "whatever";
$results = DB::select(DB::raw('SELECT
t.id, t.AvgStyle, r.RateDesc
FROM (
SELECT
p.id, ROUND(AVG(s.Value)) AS AvgStyle
FROM posts p
INNER JOIN styles s
ON s.post_id = p.id
WHERE author = $x
GROUP BY p.id
) t
INNER JOIN rates r
ON r.digit = t.AvgStyle'
));
【问题讨论】:
所以让我们从简单的开始:除非您使用双引号,否则 php 不会进行变量插值。让我们从那个开始。更改您的 sql 语句以使用“SELECT ...”并报告正在发生的任何行为。 我看到的第二个明显的事情 --- 作者是 char/varchar 值吗?如果是这样,您的 sql 语法必须是 WHERE author = '$x' 。 RAW 方法的目的是注入原始 sql,所以它不会为你做任何魔术。您必须构建一个可以复制到命令行工具并运行它的字符串。 你解决了!请把它作为一个答案来获得你的信任。 6000多点的智商不是白给的。 好的,不用担心,很高兴能帮上忙。 我很感激,但如果我们不把它作为答案,每个人都会继续检查它,因为它仍然像未解决一样。 【参考方案1】:这似乎是一个简单的 PHP 变量插值问题。
DB::raw()
想要 raw SQL。因此,您传递的 SQL 字符串中有几个问题需要修复。
-
PHP 变量插值(将变量注入字符串)只有在字符串周围使用双引号时才会发生。使用单引号,它变成一个字符串常量。
如果 Author 是
char
/varchar
,则 SQL 语法需要在原始 SQL 语句中的字符串两边加上引号。查询构建器通常会为您解决这些问题,但您会绕过它们。
所以“固定”版本是:
$x = "whatever";
$results = DB::select(DB::raw("SELECT
t.id, t.AvgStyle, r.RateDesc
FROM (
SELECT
p.id, ROUND(AVG(s.Value)) AS AvgStyle
FROM posts p
INNER JOIN styles s
ON s.post_id = p.id
WHERE author = '$x'
GROUP BY p.id
) t
INNER JOIN rates r
ON r.digit = t.AvgStyle"
));
像所有插值一样,如果被插值的变量来自用户输入,这会为您带来 SQL 注入的可能性。从最初的问题来看,这是否是一个问题尚不清楚。
DB::select()
有一个选项,允许您传递一个对 SQL 注入本质上是安全的参数数组。在这种情况下,解决方案是:
$x = "whatever";
$results = DB::select(DB::raw("SELECT
t.id, t.AvgStyle, r.RateDesc
FROM (
SELECT
p.id, ROUND(AVG(s.Value)) AS AvgStyle
FROM posts p
INNER JOIN styles s
ON s.post_id = p.id
WHERE author = :author
GROUP BY p.id
) t
INNER JOIN rates r
ON r.digit = t.AvgStyle"
),
array('author' => $x)
);
【讨论】:
旁注:这里没有参数绑定,也没有转义,所以使用此代码的读者应该确保$x
不是来自用户输入。
@halfer 根据我的测试,该参数是安全的,因为我可以将where name = :name
与['name' => "o'brien"]
一起使用。如果它没有转义那个撇号,查询就会失败。
@halfer:您的评论与非参数传递版本有关,我个人不提倡也不会使用。如果您不需要转义,那么参数化查询就是您要走的路,这也会使您免受 SQL 注入的影响。
如果您在 select 方法中有多个值,则此方法不起作用
我不明白你的意思——“select 方法中有多个值”。【参考方案2】:
关于this tutorial
$results = DB::select( DB::raw("SELECT * FROM some_table WHERE some_col = :somevariable"), array(
'somevariable' => $someVariable,
));
【讨论】:
如果您在 select 方法中有多个值,则此方法不起作用【参考方案3】:这是一个在原始 sql laravel 中插入变量的示例
$query_result = Event::select(
DB::raw('(CASE WHEN status = "draft" THEN "draft"
WHEN events.end_time <= \''.$now.'\' THEN "closed"
ELSE "available"
END) AS status'))
->orderBy('status')
->get();
【讨论】:
请解释您的解决方案,而不是只显示代码。以上是关于在原始 sql 查询 Laravel 中插入变量的主要内容,如果未能解决你的问题,请参考以下文章
在 Laravel 5 Eloquent 中获取原始 SQL 查询的结果