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中无法做到这一点。我们生活在一个多么疯狂的世界。
答案 0 :(得分:2)
每当我想让用户在查询中输入列名作为变量(例如排序和过滤器)时,是否必须创建列名称的白名单以清理用户输入?
是
PDO本身不允许绑定列名,
完全。
嗯,在某种程度上。在我自己的DB包装器中,我有一个占位符表示列名。 Dunno for Laravel但他们也可能有一些东西。现代网络世界中是否真的没办法将列名安全地绑定到查询?
然而,无论如何,白名单最好。