1

我对 PDO 还很陌生,所以如果我误解了一些事情,请原谅。我花了很长时间阅读网上可用的材料,但找不到合适的解决方案。

我正在尝试编写的代码应该执行以下操作:获取两个包含特定点纬度 ($lat) 和经度 ($lon) 的 $_GET 变量,然后选择最接近存储在启用 PostGIS 的数据库中的这些坐标的点(加上到该点的返回距离)。这是当前(和工作)代码片段的样子:

$courts = $pdo->query("SELECT * , ST_ASTEXT(geog) , ST_distance( ST_GeographyFromText('POINT($lon $lat)') , geog ) AS distance FROM bvbcourts WHERE ST_DWithin( ST_GeographyFromText('POINT($lon $lat)' ) , geog , 20000) ORDER BY distance LIMIT 1");

但是,我想尝试使用 prepare 语句,因为我读到这些是 SQL 注入证明。

$courts = $pdo->prepare("SELECT * , ST_ASTEXT(geog) , ST_distance( ST_GeographyFromText('POINT( :lon :lat )') , geog ) AS distance FROM bvbcourts WHERE ST_DWithin( ST_GeographyFromText('POINT( :lon :lat )' ) , geog , 20000) ORDER BY distance LIMIT 1" );
$courts->execute(array( ':lon' => $lon , ':lat' => $lat ) )

但是上面的代码不起作用。执行errorInfo()只返回如下错误码:HY093

根据我目前所学的内容,我假设上面的代码不起作用,因为->prepare占位符只能用于通常插入输入参数的地方。

例如->prepare( "SELECT * FROM x WHERE field=:field" );会工作而->prepare( "SELECT * FROM x WHERE field='someprefix:field'" );不会。我在上面尝试使用的代码有点类似于“someprefix”示例。

所以,我的问题是,我如何让我试图执行的语句生效,而不必使用->query和手动阻止注入。或者我最好确保传递的参数是正确的、简单的坐标和使用->query

这只是我在这里提出的第二个问题,如果我对所提供的研究和信息不够清楚或透彻,请原谅。

4

2 回答 2

2

我真的很想知道如何使新人可以使用该主题的基本知识。

对于一个常看的人来说,这些问题似乎是相当重复的。这使程序员认为网站效率低下。然而,网站政策似乎鼓励重复问题。所以,就这样吧。

准备好的语句只能表示完整的数据文字。坦率地说 - 一个完整的字符串数字

看看你的代码:

'POINT($lon $lat)'

已经是数据文字了。因此,您不能使文字成为文字的一部分。您必须将其全部绑定:

$courts = $pdo->prepare("SELECT * , ST_ASTEXT(geog) , ST_distance( ST_GeographyFromText(:point) , geog ) AS distance FROM bvbcourts WHERE ST_DWithin( ST_GeographyFromText(:point ) , geog , 20000) ORDER BY distance LIMIT 1" );
$courts->execute(array( ':point' => "POINT($lon $lat)") );
于 2013-08-21T21:28:15.357 回答
2

最好的方法是创建 WKT 字符串,而是将坐标浮点数直接传递给 PostGIS 几何构造函数。这是您的准备语句应该是什么样子。

SELECT *, ST_ASTEXT(geog), ST_Distance(poi, geog) AS distance
FROM bvbcourts,
 (SELECT ST_MakePoint(:lon, :lat)::geography AS poi) AS f
WHERE ST_DWithin(poi, geog, 20000)
ORDER BY distance
LIMIT 1;
于 2013-08-22T00:24:48.813 回答