在Laravel 4中如何转义原始SQL查询

36

在Laravel 4中如何转义传递给原始查询的参数?我期望能有类似于Laravel 3中的DB :: escape()(这让我想起了)并尝试了DB :: quote() (我认为可能可以通过PDO对象获得)

$query = DB::select("SELECT * FROM users WHERE users.id = " . DB::escape($userId));

由于上述内容只是我们尝试实现的一个简化示例,因此无法使用占位符的select方法。 我们有一个大型自定义查询,其中包含几个嵌套的select查询,无法适应查询构建器。

在插入Laravel 4之前转义某些内容的最佳方法是什么?

编辑:

我刚发现可以访问PDO对象并在其上使用引用函数。这还是最好的方法,还是有更简单的访问此函数的方法?

DB::connection()->getPdo()->quote("string to quote");

谢谢。如果您包括解决方案,我会给您加1分(您也可以将其单独发布为答案并接受它...这可能会为我们节省一些时间)。 - J. Bruni
1
@J.Bruni,说得好!我现在已经将它作为一个实际的答案添加了进去,这样应该更容易找到了。 - Dwight
8个回答

64

您可以通过DB门面这种方式引用字符串。

DB::connection()->getPdo()->quote("string to quote");

我在发现这个答案时将其放在了我的问题中,但是现在我将其作为一个真正的答案放进去,以便其他人更容易找到。


4
谢谢!人们非常执着于回答错误的问题,真是令人惊奇。我需要和你一样的答案,而参数在我的情况下也无法工作。 - Gabriel Magana
1
可以运行,但调用太长了!DB::escape() 会更好。 - Andrew
@Andrew 概述了框架的功能 - Martin Zvarík

23
$value = Input::get("userID");

$results = DB::select( DB::raw("SELECT * FROM users WHERE users.id = :value"), array(
   'value' => $value,
 ));

更多细节请点击这里


4
这并没有回答问题,它说明我不是在寻找带有占位符的解决方案,而是适当地转义一个变量的方法。 - Dwight
1
@Dwight:就像无关紧要一样。当您转义以将变量值实际编码为SQL时,占位符也会这样做。PDO也是如此。 - hakre
1
注意,我在与更多的where语句结合使用时遇到了问题。查询构建器不会像where中的其他动态替换一样组合select()中的占位符。 - tomvo
@hakre 如果我需要转义一堆(数量不定)变量以放入语句的“IN ()”部分,该怎么办? - Jānis Elmeris
1
@Janis:你可以在Can I bind an array to an IN() condition?及其相关问答中找到这类问题的答案。 - hakre

11

你也可以尝试这个方法,(阅读文档)

$results = DB::select('SELECT * FROM users WHERE users.id = ?', array($userId));

2
使用数组绑定,就像上面的例子一样,可以保护您。更多信息请参见http://forums.laravel.io/viewtopic.php?id=11068 - Laurence
1
这并没有回答问题,它表明我不是在寻找带有占位符的解决方案,而是适当地转义一个变量的方法。 - Dwight
1
@Dwight,array binding/bound params的作用是安全的、转义的,不会受到SQL注入的影响,而且不仅仅是占位符。只需阅读此答案,你就能明白了。 - The Alpha
@Dwight,还注意到第一条评论了吗?它难道没有澄清你的疑问吗? - The Alpha

7

以下是我使用的两种解决方案,都基于 DB 门面提供了更简洁的解决方案。

第一种是值引用

// From linked answer
DB::connection()->getPdo()->quote("string to quote");
// In the DB facade
DB::getPdo()->quote('string to quote');

其次,标识符引用(表名和列名):identifier quoting

// From linked answer
DB::table('x')->getGrammar()->wrap('table.column');
// In the DB facade
DB::getQueryGrammar()->wrap('table.column');

5

当我在寻找Laravel中通用的SQL转义时,我发现了这个问题。但实际上我需要的是表/列名的转义。因此,供以后参考:

/**
 * Quotes database identifier, e.g. table name or column name. 
 * For instance:
 * tablename -> `tablename`
 * @param  string $field 
 * @return string      
 */
function db_quote_identifier($field) {
  static $grammar = false;
  if (!$grammar) {
    $grammar = DB::table('x')->getGrammar(); // The table name doesn't matter.
  }
  return $grammar->wrap($field);
}

DB::query()->getGrammar() 可能是一种更直接的方法。这样可以避免其他开发人员问太多问题。 - amphetamachine

4

我在Laravel 5的helpers.php中使用了以下代码:

if ( ! function_exists('esc_sql'))
{
    function esc_sql($string)
    {
        return app('db')->getPdo()->quote($string);
    }
}

那么我可以在需要对原始SQL查询进行转义的地方使用esc_sql函数。


0

这里是一个更完整的示例,展示如何转义值和列并扩展Laravel的查询构建器:

<?php

namespace App\Providers;

use Illuminate\Database\Query\Builder;
use Illuminate\Support\ServiceProvider;


class DatabaseQueryBuilderMacroProvider extends ServiceProvider {

    public function register() {
        Builder::macro('whereInSet', function($columnName, $value) {
            /** @var \Illuminate\Database\Query\Grammars\Grammar $grammar */
            $grammar = $this->getGrammar();
            return $this->whereRaw('FIND_IN_SET(?,' . $grammar->wrap($columnName) . ')', [$value]);
        });
    }
}

0

PHP Heredoc

{{链接1:PHP Heredoc}}

<?php

use Illuminate\Support\Facades\DB;

$sql = <<<SQL
  WITH table1 AS(SELECT...
SQL;

$parameters = [1,2,3,...]

$table = DB::select($sql, $parameters);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接