在 Laravel / PDO 中绑定列
Posted
技术标签:
【中文标题】在 Laravel / PDO 中绑定列【英文标题】:Binding Columns in Laravel / PDO 【发布时间】:2014-06-05 22:18:10 【问题描述】:TL;DR:为了让用户对数据集进行排序,我真的必须创建列名白名单(与清理用户输入时进行比较)吗? 开销太大了,在现代 php 世界中,真的没有办法用变量代替吗?
全文:
我想让用户选择在数据集中对结果进行排序的列和方向。
我已经通过以下代码实现了这一点:
$sort = Input::get('sort'); // The column name to sort by
$direction = Input::get('direction'); // 'asc' / 'desc'
$paginator = DB::table('master')
->select('Style_ID', DB::raw('MAX(?) AS `sort`'))
->setBindings(array($sort))
->orderBy('sort', $direction)
->groupBy('Style_ID')
->paginate(20);
$masters = $paginator->getCollection();
这运行没有错误,但生成的 20 行似乎完全忽略了请求的聚合 MAX。
这是该代码上查询日志的输出:
(
[query] => select `Style_ID`, MAX(?) AS `sort` from `master` group by `Style_ID` order by `sort` desc
[bindings] => Array
(
[0] => Hot
)
[time] => 2
)
...所以查询看起来不错,但结果却不行。
它确实有效,但是,如果我删除列绑定和列中的硬编码:
$paginator = DB::table('master')
->select('Style_ID', DB::raw('MAX(`Hot`) AS `sort`'))
->orderBy('sort', $direction)
->groupBy('Style_ID')
->paginate(20);
$masters = $paginator->getCollection();
查询日志为:
(
[query] => select `Style_ID`, MAX(`hot`) AS `sort` from `master` group by `Style_ID` order by `sort` desc
[bindings] => Array
(
)
[time] => 2
)
这让我相信 Laravel 或 PDO 本身都不允许绑定列名,尽管这对我来说毫无意义。在这种情况下,我会收到一条错误消息。
我被难住了。提前感谢您的帮助。
一种可能的解决方案是,如果我们能够以某种方式转义列名而不是绑定它:
->select('Style_ID', DB::raw('MAX(`' . DB::escape($sort) . '`) AS `sort`'))
...但是没有那样的东西,是吗? mysql_real_escape_string
is deprecated 和 PDO 没有替代它。
我是否别无选择,只能在每次我想做这样的事情来清理输入时创建所有列名的白名单?
根据this question/answer,PHP 没有办法做到这一点。我们生活在一个多么疯狂的世界。
【问题讨论】:
【参考方案1】:如果我想让用户在查询中输入列名作为变量(例如排序和过滤器),是否必须创建列名白名单来清理用户输入?
是的。
PDO 本身不允许绑定列名,
没错。
现代网络世界中真的没有办法安全地将列名绑定到查询吗?
嗯,在某种程度上。在我自己的数据库包装器中,我有一个用于列名的占位符。不知道 Laravel 的情况,但他们可能也有一些袖手旁观的东西。
不过,最好还是列入白名单。
【讨论】:
我在 Laravel 中设置了一个类似的数组。多可惜!哦,好的,谢谢老兄。以上是关于在 Laravel / PDO 中绑定列的主要内容,如果未能解决你的问题,请参考以下文章