在 Laravel 4 中转义原始 SQL 查询

Posted

技术标签:

【中文标题】在 Laravel 4 中转义原始 SQL 查询【英文标题】:Escape raw SQL queries in Laravel 4 【发布时间】:2013-09-27 20:46:39 【问题描述】:

如何在 Laravel 4 中转义传递给原始查询的参数?我期待像 DB::escape() 之类的东西(它从 Laravel 3 中敲响了钟声)并且还尝试了 DB::quote() (我认为可以通过 PDO object 获得)

$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】:
$value = Input::get("userID");

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

更多详情HERE

【讨论】:

这并没有回答问题,它表明我不是在寻找带有占位符的解决方案,而是寻找逃避一个变量的适当方法。 @Dwight:没有实际意义。当您转义以将变量值实际编码为 SQL 时,占位符也是如此。 PDO 也是如此。 当心,我在使用这个结合更多 where 语句时遇到了问题。查询生成器不会组合 select() 中的占位符和 where 中的其他动态替换。 @hakre 如果我需要转义一堆(可变数量)变量以放入语句的“IN ()”部分怎么办? @Janis:你会在Can I bind an array to an IN() condition? 中找到这些问题的答案,这是姐妹问答。【参考方案2】:

你也可以试试这个,(Read Documentation)

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

【讨论】:

+1 对此答案。使用数组绑定,就像上面的例子,会保护你。更多信息在这里forums.laravel.io/viewtopic.php?id=11068 这并没有回答问题,它表明我不是在寻找带有占位符的解决方案,而是寻找逃避一个变量的适当方法。 @Dwight,这就是array binding/bound params 所做的,安全的,转义的,不能应用 sql 注入,而不仅仅是占位符。只需阅读this answer 即可清除自己。 @Dwight,还注意到第一条评论,它没有澄清你吗?【参考方案3】:

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

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

当我发现这个答案时,我确实把它放在了我的问题中,但是我现在把它作为一个实际的答案放进去,以便其他人更容易找到。

【讨论】:

谢谢!令人惊讶的是,人们如何坚持回答错误的问题。我需要和你一样的答案,而且参数在我的情况下也不起作用。 有效,但要调用这么长时间! DB::escape() 会很好。【参考方案4】:

我在 Laravel 5 的 helpers.php 中使用它:

if ( ! function_exists('esc_sql'))

    function esc_sql($string)
    
        return app('db')->getPdo()->quote($string);
    

然后我可以使用esc_sql 函数来执行原始 SQL 查询的转义。

【讨论】:

【参考方案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() 可能是一种更直接的方法。防止其他开发人员问太多问题。【参考方案6】:

这是一个更完整的示例,展示了如何转义值和列并扩展 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]);
        );
    

【讨论】:

【参考方案7】:

我在这里使用的两个答案在DB 外观中内置了不太冗长的解决方案。

首先,value quoting:

// 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');

【讨论】:

以上是关于在 Laravel 4 中转义原始 SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章

在rails中转义SQL LIKE的查询

在 Codeigniter 中转义 SQL 查询

努力在 SQL 查询 C# QODBC 中转义单引号

NamedParameterJdbcTemplate Oracle SQL,如何在命名查询中转义单引号?

在 Laravel Blade 中转义 VueJS 数据绑定语法?

在 SQL 字符串中转义 & 字符