我有一些查询需要使用查询构建器
传递给另一个查询$query = DB::table('table')->whereIn('some_field', [1,2,30])->toSql();
Model::join(DB::raw("({$query}) as table"), function($join) {
$join->on('model.id', '=', 'table.id');
})
应该以
结果Select * from model join (select * from table where some_field in (1,2,30)) as table on model.id = table.id
但是没有传递绑定,这迫使我做
$query = DB::table('table')->whereRaw('some_field in ('. join(',', [1,2,30]) .')')->toSql();
有时可能不安全。如何通过绑定获取查询?
答案 0 :(得分:18)
查看getBindings()
类
Builder
方法
$query = DB::table('table')->whereIn('some_field', [1,2,30]);
$sql = $query->toSql();
$bindings = $query->getBindings();
答案 1 :(得分:5)
public static function getQueries(Builder $builder)
{
$addSlashes = str_replace('?', "'?'", $builder->toSql());
return vsprintf(str_replace('?', '%s', $addSlashes), $builder->getBindings());
}
答案 2 :(得分:1)
以下函数通过将?
括为'?'
public static function getFinalSql($query)
{
$sql_str = $query->toSql();
$bindings = $query->getBindings();
$wrapped_str = str_replace('?', "'?'", $sql_str);
return str_replace_array('?', $bindings, $wrapped_str);
}
答案 3 :(得分:1)
由于其他答案未正确引用表达式,因此这是我的方法。它使用属于当前数据库连接的转义功能。
它用相应的绑定一一替换问号,该绑定通过array_shift()从$ bindings中检索,在此过程中消耗了数组。请注意,必须通过引用传递$ bindings才能起作用。
function getSql($query)
{
$bindings = $query->getBindings();
return preg_replace_callback('/\?/', function ($match) use (&$bindings, $query) {
return $query->getConnection()->getPdo()->quote(array_shift($bindings));
}, $query->toSql());
}
答案 4 :(得分:1)
您可以执行以下操作:
$escapedBindings = array();
foreach($query->getBindings() as $item) {$escapedBindings[] = '"'.$item.'"';}
$sql_with_bindings = Str::replaceArray('?', $escapedBindings, $query->toSql());
答案 5 :(得分:1)
这是一个非常老的问题(2015年),但是由于这是Google的第一个结果,我认为也有必要提供我的解决方案,以防对下一个人有用。
雄辩的语言(我认为5.7以后,我还没有测试较新的或更早的版本)提供了一种方法来更改构建器的from
来包装子查询:
# Taken from Illuminate/Database/Query/Builder.php - Line 272
public function fromSub($query, $as) {
[$query, $bindings] = $this->createSub($query);
return $this->fromRaw('('.$query.') as '.$this->grammar->wrapTable($as), $bindings);
}
但是,这需要\Illuminate\Database\Query\Builder
的现有实例。为了制作一个空的,您可以执行以下操作:
use Illuminate\Database\Capsule\Manager as DB;
$fancy = DB::table("videogames")->where("uses_sdl2", 1);
$empty = DB::table(null);
# Wrap the fancy query and set it as the "from" clause for the empty one
# NOTE: the alias is required
$empty = $empty->fromSub($fancy, "performant_games");
这将保证绑定得到正确的处理,因为它们将由Eloquent本身处理。
答案 6 :(得分:1)
$sqlQuery = Str::replaceArray(
'?',
collect($query->getBindings())
->map(function ($i) {
if (is_object($i)) {
$i = (string)$i;
}
return (is_string($i)) ? "'$i'" : $i;
})->all(),
$query->toSql());
答案 7 :(得分:0)
如果要从查询日志中获取包含绑定的已执行查询:
\DB::enableQueryLog();
\DB::table('table')->get();
dd(str_replace_array('?', \DB::getQueryLog()[0]['bindings'],
\DB::getQueryLog()[0]['query']));
答案 8 :(得分:0)
我创建了这个功能。它是局部的,可能是未涵盖的参数,对我来说就足够了。
非常欢迎在评论中添加您的改进!
function getFullSql($query) {
$sqlStr = $query->toSql();
foreach ($query->getBindings() as $iter=>$binding) {
$type = gettype($binding);
switch ($type) {
case "integer":
case "double":
$bindingStr = "$binding";
break;
case "string":
$bindingStr = "'$binding'";
break;
case "object":
$class = get_class($binding);
switch ($class) {
case "DateTime":
$bindingStr = "'" . $binding->format('Y-m-d H:i:s') . "'";
break;
default:
throw new \Exception("Unexpected binding argument class ($class)");
}
break;
default:
throw new \Exception("Unexpected binding argument type ($type)");
}
$currentPos = strpos($sqlStr, '?');
if ($currentPos === false) {
throw new \Exception("Cannot find binding location in Sql String for bundung parameter $binding ($iter)");
}
$sqlStr = substr($sqlStr, 0, $currentPos) . $bindingStr . substr($sqlStr, $currentPos + 1);
}
$search = ["select", "distinct", "from", "where", "and", "order by", "asc", "desc", "inner join", "join"];
$replace = ["SELECT", "DISTINCT", "\n FROM", "\n WHERE", "\n AND", "\n ORDER BY", "ASC", "DESC", "\n INNER JOIN", "\n JOIN"];
$sqlStr = str_replace($search, $replace, $sqlStr);
return $sqlStr;
}
答案 9 :(得分:0)
Laravel现在可以直接在Builder上进行调试!!!
https://laravel.com/docs/queries#debugging
\App\User::where('age', '18')->dump();
\App\User::where('age', '18')->dd();
输出
"select * from `users` where `age` = ?"
[
0 => "18"
]
答案 10 :(得分:0)
您可以将以下代码块定义为辅助函数,并在需要时使用。 它将数字和字符串值用引号绑定。
public static function getSqlWithBindings($query)
{
return vsprintf(str_replace('?', '%s', $query->toSql()), collect($query->getBindings())->map(function ($binding) {
return is_numeric($binding) ? $binding : "'{$binding}'";
})->toArray());
}
示例:
$query = Document::where('model', 'contact')->where('model_id', '1');
dd(Document::getSqlWithBindings($query));
输出:
"select * from `document` where `model` = 'contact' and `model_id` = 1"
答案 11 :(得分:0)
以Douglas.Sesar的答案为基础。
我发现我还需要将绑定放在单引号中,以便能够轻松将其粘贴到我的数据库IDE中。
$sql = $query->toSql();
$bindings = $query->getBindings();
$sql_with_bindings = preg_replace_callback('/\?/', function ($match) use ($sql, &$bindings) {
return "'" . array_shift($bindings) . "'";
}, $sql);
答案 12 :(得分:-1)
将所有已插入绑定的查询从最慢查询到最快排序的日志输出到日志:
import ReactDOM from "react-dom";
import React from "react";
class Todo extends React.Component {
state = {
text1: "",
text2: "",
interval: null
};
componentDidMount() {
this.setState({
interval: setInterval(() => {
const { text1, text2 } = this.state;
const autoSaveObject = {
text1,
text2
};
console.log(JSON.stringify(autoSaveObject));
}, 3000)
});
}
componentWillUnmount() {
clearInterval(this.state.interval);
}
render() {
return (
<div>
<h1>TODO LIST</h1>
<form>
<input
value={this.state.text1}
onChange={e => this.setState({ text1: e.target.value })}
/>
<input
value={this.state.text2}
onChange={e => this.setState({ text2: e.target.value })}
/>
</form>
</div>
);
}
}
ReactDOM.render(<Todo />, document.getElementById("root"));
答案 13 :(得分:-3)
这里都解释了..... https://ajcastro29.blogspot.com/2017/11/laravel-join-derived-tables-properly.html
我为那个东西创建了一个范围查询。我认为它也可以在宏中......
public function scopeJoinDerived($query, $derivedQuery, $table, $one, $operator = null, $two = null, $type = 'inner', $where = false)
{
$query->join(DB::raw("({$derivedQuery->toSql()}) as `{$table}`"), $one, $operator, $two, $type, $where);
$join = last($query->getQuery()->joins);
$join->bindings = array_merge($derivedQuery->getBindings(), $join->bindings);
return $query;
}