【发布时间】: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 没有办法做到这一点。我们生活在一个多么疯狂的世界。
【问题讨论】: